canvas画布:绘制转动的椭圆形环绕文本
本帖最后由 马黑黑 于 2024-5-14 20:34 编辑 <br /><br /><style>.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; color: black; background: rgba(240, 240, 240,.95); box-shadow: 2px 2px 4px gray; border: thick groove lightblue; border-radius: 6px; }
.mum ::selection { background-color: rgba(0,100,100,.35); }
.mum div { margin: 0; padding: 0; }
.mum cl-cd { display: block; position: relative; margin: 0 0 0 50px; padding: 0 0 0 10px; white-space: pre-wrap; overflow-wrap: break-word; border-left: 1px solid silver; }
.mum cl-cd::before { position: absolute; content: attr(data-idx); width: 50px; color: gray; text-align: right; transform: translate(-70px); }
.tRed { color: red; }
.tBlue { color: blue; }
.tGreen { color: green; }
.tDarkRed { color: darkred; }
.tMagenta { color: magenta; }
.tMid { text-align: center; }
</style>
<h2>效果</h2>
<p class="tMid"><canvas id="mycanv" width="600" height="360"></canvas></p>
<h2>代码</h2>
<div class='mum'>
<cl-cd data-idx="1"><<span class="tDarkRed">canvas</span> <span class="tRed">id</span>=<span class="tMagenta">"mycanv"</span> width=<span class="tMagenta">"600"</span> height=<span class="tMagenta">"360"</span> style=<span class="tMagenta">"<span class="tBlue">border:</span>1px solid gray"</span>><<span class="tDarkRed">/canvas</span>></cl-cd>
<cl-cd data-idx="2"> </cl-cd>
<cl-cd data-idx="3"><<span class="tDarkRed">script</span>></cl-cd>
<cl-cd data-idx="4"> </cl-cd>
<cl-cd data-idx="5"><span class="tBlue">var</span> ww = mycanv.width, hh = mycanv.height, deg = -90;</cl-cd>
<cl-cd data-idx="6"><span class="tBlue">var</span> ctx = mycanv.getContext(<span class="tMagenta">'2d'</span>);</cl-cd>
<cl-cd data-idx="7"> </cl-cd>
<cl-cd data-idx="8"><span class="tBlue">class </span>ccText {</cl-cd>
<cl-cd data-idx="9"> constructor(text) {</cl-cd>
<cl-cd data-idx="10"> <span class="tBlue">this</span>.chars = text.split(<span class="tMagenta">''</span>);</cl-cd>
<cl-cd data-idx="11"> <span class="tBlue">this</span>.colors = <span class="tBlue">this</span>.chars.map(color => `#${<span class="tRed">Math</span>.random().toString(16).substr(2,6)}`);</cl-cd>
<cl-cd data-idx="12"> };</cl-cd>
<cl-cd data-idx="13"> draw(context) {</cl-cd>
<cl-cd data-idx="14"> context.font = <span class="tMagenta">'bold 60px sans-serif'</span>;</cl-cd>
<cl-cd data-idx="15"> context.textAlign = <span class="tMagenta">'center'</span>;</cl-cd>
<cl-cd data-idx="16"> context.textBaseline = <span class="tMagenta">'middle'</span>;</cl-cd>
<cl-cd data-idx="17"> context.shadowOffsetX = -2;</cl-cd>
<cl-cd data-idx="18"> context.shadowOffsetY = 2;</cl-cd>
<cl-cd data-idx="19"> context.shadowColor = <span class="tMagenta">'#000'</span>;</cl-cd>
<cl-cd data-idx="20"> context.shadowBlur = 4;</cl-cd>
<cl-cd data-idx="21"> <span class="tBlue">var</span> a = 360 / <span class="tBlue">this</span>.chars.length, r1 = ww/2 - 40, r2 = hh/2 - 40;</cl-cd>
<cl-cd data-idx="22"> <span class="tBlue">this</span>.chars.forEach((<span class="tBlue">char</span>,key) => {</cl-cd>
<cl-cd data-idx="23"> <span class="tBlue">var</span> rad = (a * key + deg) * <span class="tRed">Math</span>.PI / 180;</cl-cd>
<cl-cd data-idx="24"> <span class="tBlue">var</span> x = ww/2 + r1 * <span class="tRed">Math</span>.cos(rad), y = hh/2 + r2 * <span class="tRed">Math</span>.sin(rad);</cl-cd>
<cl-cd data-idx="25"> context.fillStyle = <span class="tBlue">this</span>.colors;</cl-cd>
<cl-cd data-idx="26"> context.fillText(<span class="tBlue">char</span>, x, y);</cl-cd>
<cl-cd data-idx="27"> });</cl-cd>
<cl-cd data-idx="28"> };</cl-cd>
<cl-cd data-idx="29">};</cl-cd>
<cl-cd data-idx="30"> </cl-cd>
<cl-cd data-idx="31"><span class="tBlue">var</span> cc = <span class="tBlue">new</span> ccText(<span class="tMagenta">'風和日麗囍看萬紫千紅'</span>);</cl-cd>
<cl-cd data-idx="32"> </cl-cd>
<cl-cd data-idx="33"><span class="tBlue">var</span> render = () => {</cl-cd>
<cl-cd data-idx="34"> requestAnimationFrame(render);</cl-cd>
<cl-cd data-idx="35"> ctx.clearRect(0, 0, ww, hh);</cl-cd>
<cl-cd data-idx="36"> deg = (deg + 0.5) % 360;</cl-cd>
<cl-cd data-idx="37"> cc.draw(ctx);</cl-cd>
<cl-cd data-idx="38">};</cl-cd>
<cl-cd data-idx="39"> </cl-cd>
<cl-cd data-idx="40">render();</cl-cd>
<cl-cd data-idx="41"> </cl-cd>
<cl-cd data-idx="42"><<span class="tDarkRed">/script</span>></cl-cd>
</div>
<script>
var ww = mycanv.width, hh = mycanv.height, deg = -90;
var ctx = mycanv.getContext('2d');
class ccText {
constructor(text) {
this.chars = text.split('');
this.colors = this.chars.map(color => `#${Math.random().toString(16).substr(2,6)}`);
};
draw(context) {
context.font = 'bold 60px sans-serif';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.shadowOffsetX = -2;
context.shadowOffsetY = 2;
context.shadowColor = '#000';
context.shadowBlur = 4;
var a = 360 / this.chars.length, r1 = ww/2 - 40, r2 = hh/2 - 40;
this.chars.forEach((char,key) => {
var rad = (a * key + deg) * Math.PI / 180;
var x = ww/2 + r1 * Math.cos(rad), y = hh/2 + r2 * Math.sin(rad);
context.fillStyle = this.colors;
context.fillText(char, x, y);
});
};
};
var cc = new ccText('風和日麗囍看萬紫千紅');
var render = () => {
requestAnimationFrame(render);
ctx.clearRect(0, 0, ww, hh);
deg = (deg + 0.5) % 360;
cc.draw(ctx);
};
render();
</script>
相比静态椭圆坏绕文本,这里:
一、构造函数多了一个 colors数组,它由文本拆分后的数组迭代而来,里面储存的随机颜色对应于每一个文本个体;
二、添加一个渲染函数 render() ,通过调用请求关键帧动画API requestAnimationFrame() 每一次屏幕刷新给角度变量 deg 加上0.5 度,度数的变化在360度范围内循环。该函数利用角度的变化不断绘制相同的文本,形成文本旋转的效果。 代码里还给文字添加个边框,可以看出和边界的关系了呢{:4_204:} 这个转动的还能做到随机色,太厉害了{:4_199:}
如果是纯色的,就不需要这么麻烦了吧。 红影 发表于 2024-5-14 21:30
这个转动的还能做到随机色,太厉害了
如果是纯色的,就不需要这么麻烦了吧。
少一行代码而已 deg = (deg + 0.5) % 360; 可以调整速度,数字越小,速度越慢。 红影 发表于 2024-5-14 21:29
代码里还给文字添加个边框,可以看出和边界的关系了呢
是的,不过一楼实例没有边框 红影 发表于 2024-5-14 21:31
deg = (deg + 0.5) % 360; 可以调整速度,数字越小,速度越慢。
是的 下午在想这些字明天会动起来吧。。原来12小时不到。。{:4_170:} 南无月 发表于 2024-5-14 21:38
下午在想这些字明天会动起来吧。。原来12小时不到。。
这个哪里需要那么多时间?关键是想不想做 马黑黑 发表于 2024-5-14 21:30
少一行代码而已
只多一行代码,就能随机色,厉害{:4_199:} 马黑黑 发表于 2024-5-14 21:31
是的,不过一楼实例没有边框
是的,我去试了代码才看到边框的{:4_173:} 马黑黑 发表于 2024-5-14 21:32
是的
这个速度也去试了验证了一下{:4_187:} 马黑黑 发表于 2024-5-14 21:39
这个哪里需要那么多时间?关键是想不想做
看了一会挺好玩,字变大小,加字减字,变快变慢,改颜色,改位置,变圆,竖椭圆都可以。。{:4_170:}
这个好灵活啊。。跑得很流畅,看着很治愈 马黑黑 发表于 2024-5-14 21:39
这个哪里需要那么多时间?关键是想不想做
从想法到实现,你给修了一条高速路的节奏{:4_170:} 南无月 发表于 2024-5-14 22:04
从想法到实现,你给修了一条高速路的节奏
木有钱钱买高铁票 南无月 发表于 2024-5-14 21:49
看了一会挺好玩,字变大小,加字减字,变快变慢,改颜色,改位置,变圆,竖椭圆都可以。。
...
多看免疫力会更强,刀子嗓会不治而愈 红影 发表于 2024-5-14 21:49
这个速度也去试了验证了一下
速度合适就好 红影 发表于 2024-5-14 21:48
只多一行代码,就能随机色,厉害
16进制随机颜色不久一行代码就可以实现的吗?
还有 rgb 随机颜色,也可以一行代码实现;hsl 也行。明天有空我试试。 马黑黑 发表于 2024-5-14 22:55
木有钱钱买高铁票
自己修的高铁自家的和谐号不用票{:4_170:}