环形文字旋转的实现

需求如下图:

中间的地球是个gif图哈,但是我记得通过无缝滚动也可以实现地球滚动,这里主要看的是地球周围的滚动文字,要实现这个效果,有两种方法:

  1. SVG直接绘制
  2. CSS+JS

因为我这次用的是uniapp,它老是把SVG标签内的 text 标签解析成 uni-text,跟个癫公一样,因此这里只能放弃了SVG的方案。

SVG方案

代码如下:

html 复制代码
<svg width="400" height="400">
  <path id="circlePath" d="M200,50 A150,150 0 1,1 200,349.999" fill="none" />
  <text>
    <textPath xlink:href="#circlePath">
      环形文本
    </textPath>
  </text>
</svg>

CSS+JS

实现思路

首先是一个容器view,设置为相对定位,然后内部每一个字都是一个text元素,通过绝对定位定位到同一个位置(也就是每个字都重叠在一起),然后通过js代码控制每个text元素的transform属性,最后给容器加上旋转动画即可。

实现代码

模板代码

html 复制代码
<div class="container">
	环形文字环形文字
</div>

样式代码

scss 复制代码
// 容器样式
.container {
	width: 430px;
	height: 430px;
	position: relative;
	text-align: center;
	animation: spin 20s linear infinite;
	// 文字样式
	.text {
		position: absolute;
		left: 0;
		top: 0;
		right: 0;
		bottom: 0;
		font-size: 25px;
	}
}
// 旋转动画
@keyframes spin {
	0% {
		transform: rotate(360deg);
	}
	100% {
		transform: rotate(0);
	}
}

逻辑代码

首先获取容器元素,然后复制其内部的文本,再然后将内部文本清空:

js 复制代码
const container = document.querySelector('.container')
const textContent = container.innerText
container.innerText = ''

接着遍历保存的文本内容,逐个字的遍历,每次遍历都会创建一个span元素,然后通过下标计算出其rotate的值,然后将span元素添加到容器元素中:

js 复制代码
for (let i = 0; i < textContent.length; i++) {
	const span = document.createElement('span')
	span.className = 'text'
	span.innerText = textContent[i]
	const r = i * 360 / textContent.length
	span.style.transform = `rotate(${r}deg)`
	container.appendChild(span)
}

此时在页面上就可以看到效果了:

uniapp中实现

如果是在uniapp中,可以像下面这样实现(因为我是要在移动端使用,因此尽量不操作DOM)。

模板代码

vue 复制代码
<view class="text-container">
	<template v-for="(item,index) in list">
		<view v-if="item==='n'" class="text" :style="getRoateStyle(index)">&nbsp;</view>
		<view v-else class="text" :style="getRoateStyle(index)">{{item}}</view>
	</template>
</view>

逻辑代码

首先定义一个list变量,里面存放要显示的字符:

js 复制代码
list: "nnn碎冰岛nnn雪贼岛nnn海风岛nnn费力墩补给站nnn哈尔滨补给站nnn雷霆军港nnn萨拉补给站"

这个字符串中的n是用来占位的,因为需要预留一些位置给图片。

然后定义一个getRoateStyle方法,传入index,就会返回一个计算好的动态style,如下:

js 复制代码
getRoateStyle(index) {
	const len = this.list.length
	const r = (360 / len) * index
	return {
		transform: `rotate(${r}deg)`
	}
}

此时的效果如下:

然后就到最后一步,把小岛的图片放到缝隙中,我本来是在遍历list的时候把图片给遍历出来的,结果发现,每个小岛图片的top和left值是不同的,而且是不成规律的,因此只能手写这些小岛的样式了,在模板 .text-container 中加入一个小岛的图片:

vue 复制代码
<view class="text-container">
	<!-- ... -->
	<image class="island-icon sb-island" src="/static/imgs/smartEarth/islandIcons/island1.gif" mode="aspectFill"></image>
</view>

然后手动调整位置:

css 复制代码
.island-icon {
	width: 70rpx;
	height: 70rpx;
	position: absolute;
}

// 碎冰岛
.sb-island {
	top: -20rpx;
	left: 210rpx;
}

最后实现效果如下:

相关推荐
IT_陈寒1 小时前
SpringBoot启动慢得像蜗牛?原来是这个配置在捣鬼
前端·人工智能·后端
计算机魔术师1 小时前
Muse Spark跑赢Gemini,但真正的底牌是这种设计
前端
PYB31 小时前
【Web·JS·基础】函数的使用和展运算符...objs
前端·javascript
指针向南1 小时前
Chrome读不了HEIC怎么办:原生解码和WASM两条路
前端·图像处理·人工智能·chrome·计算机视觉·wasm
默_笙2 小时前
🚥 给 RAG 装一台心电监护仪:LangSmith 全链路观测(上)
前端·javascript
前端snow3 小时前
ai agent --- mem0 外挂记忆系统
前端
变与不变8064 小时前
js同步和异步难点重点详解
开发语言·javascript·ecmascript
特立独行的猫a4 小时前
用仓颉写一个 Tauri:IPC 的每次往返实现原理(web层到仓颉层的触发过程)
前端·ui·harmonyos·tauri·鸿蒙·仓颉
Dovis(誓平步青云)4 小时前
多个链接不等于多份证据,新闻核验看板怎样合并来源
java·服务器·前端·javascript·人工智能·pdf·电脑
骑着蜗牛撵大象3274 小时前
Qt 事件机制详解:从 QEvent 派生类到事件过滤器的全景指南
前端·python