环形文字旋转的实现

需求如下图:

中间的地球是个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;
}

最后实现效果如下:

相关推荐
爱分享的程序员12 分钟前
全栈项目搭建指南:Nuxt.js + Node.js + MongoDB
前端
听吉米讲故事22 分钟前
Slidev集成Chart.js:专业数据可视化演示文稿优化指南
javascript·信息可视化·数据分析
菥菥爱嘻嘻36 分钟前
JS手写代码篇---手写 new 操作符
开发语言·javascript·原型模式
隐含1 小时前
webpack打包,把png,jpg等文件按照在src目录结构下的存储方式打包出来。解决同一命名的图片资源在打包之后,重复命名的图片就剩下一个图片了。
前端·webpack·node.js
lightYouUp1 小时前
windows系统中下载好node无法使用npm
前端·npm·node.js
Dontla1 小时前
npm cross-env工具包介绍(跨平台环境变量设置工具)
前端·npm·node.js
小妖6661 小时前
vue2 切换主题色以及单页面好使方法
前端·vue.js·elementui
胡桃夹夹子1 小时前
【前端优化】vue2 webpack4项目升级webpack5,大大提升运行速度
前端·javascript·vue.js·webpack·性能优化
Stringzhua1 小时前
JavaScript【7】BOM模型
开发语言·前端·javascript
DT——1 小时前
ECMAScript 2018(ES2018):异步编程与正则表达式的深度进化
开发语言·javascript·ecmascript