马黑黑 发表于 2024-5-14 20:31

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">&lt;<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>&gt;&lt;<span class="tDarkRed">/canvas</span>&gt;</cl-cd>
<cl-cd data-idx="2">&nbsp;</cl-cd>
<cl-cd data-idx="3">&lt;<span class="tDarkRed">script</span>&gt;</cl-cd>
<cl-cd data-idx="4">&nbsp;</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">&nbsp;</cl-cd>
<cl-cd data-idx="8"><span class="tBlue">class </span>ccText {</cl-cd>
<cl-cd data-idx="9">&nbsp; &nbsp; constructor(text) {</cl-cd>
<cl-cd data-idx="10">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">this</span>.chars = text.split(<span class="tMagenta">''</span>);</cl-cd>
<cl-cd data-idx="11">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">this</span>.colors = <span class="tBlue">this</span>.chars.map(color =&gt; `#${<span class="tRed">Math</span>.random().toString(16).substr(2,6)}`);</cl-cd>
<cl-cd data-idx="12">&nbsp; &nbsp; };</cl-cd>
<cl-cd data-idx="13">&nbsp; &nbsp; draw(context) {</cl-cd>
<cl-cd data-idx="14">&nbsp; &nbsp; &nbsp; &nbsp; context.font = <span class="tMagenta">'bold 60px sans-serif'</span>;</cl-cd>
<cl-cd data-idx="15">&nbsp; &nbsp; &nbsp; &nbsp; context.textAlign = <span class="tMagenta">'center'</span>;</cl-cd>
<cl-cd data-idx="16">&nbsp; &nbsp; &nbsp; &nbsp; context.textBaseline = <span class="tMagenta">'middle'</span>;</cl-cd>
<cl-cd data-idx="17">&nbsp; &nbsp; &nbsp; &nbsp; context.shadowOffsetX = -2;</cl-cd>
<cl-cd data-idx="18">&nbsp; &nbsp; &nbsp; &nbsp; context.shadowOffsetY = 2;</cl-cd>
<cl-cd data-idx="19">&nbsp; &nbsp; &nbsp; &nbsp; context.shadowColor = <span class="tMagenta">'#000'</span>;</cl-cd>
<cl-cd data-idx="20">&nbsp; &nbsp; &nbsp; &nbsp; context.shadowBlur = 4;</cl-cd>
<cl-cd data-idx="21">&nbsp; &nbsp; &nbsp; &nbsp; <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">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">this</span>.chars.forEach((<span class="tBlue">char</span>,key) =&gt; {</cl-cd>
<cl-cd data-idx="23">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">var</span> rad = (a * key + deg) * <span class="tRed">Math</span>.PI / 180;</cl-cd>
<cl-cd data-idx="24">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <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">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context.fillStyle = <span class="tBlue">this</span>.colors;</cl-cd>
<cl-cd data-idx="26">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context.fillText(<span class="tBlue">char</span>, x, y);</cl-cd>
<cl-cd data-idx="27">&nbsp; &nbsp; &nbsp; &nbsp; });</cl-cd>
<cl-cd data-idx="28">&nbsp; &nbsp; };</cl-cd>
<cl-cd data-idx="29">};</cl-cd>
<cl-cd data-idx="30">&nbsp;</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">&nbsp;</cl-cd>
<cl-cd data-idx="33"><span class="tBlue">var</span> render = () =&gt; {</cl-cd>
<cl-cd data-idx="34">&nbsp; &nbsp; requestAnimationFrame(render);</cl-cd>
<cl-cd data-idx="35">&nbsp; &nbsp; ctx.clearRect(0, 0, ww, hh);</cl-cd>
<cl-cd data-idx="36">&nbsp; &nbsp; deg = (deg + 0.5) % 360;</cl-cd>
<cl-cd data-idx="37">&nbsp; &nbsp; cc.draw(ctx);</cl-cd>
<cl-cd data-idx="38">};</cl-cd>
<cl-cd data-idx="39">&nbsp;</cl-cd>
<cl-cd data-idx="40">render();</cl-cd>
<cl-cd data-idx="41">&nbsp;</cl-cd>
<cl-cd data-idx="42">&lt;<span class="tDarkRed">/script</span>&gt;</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>

马黑黑 发表于 2024-5-14 20:44

相比静态椭圆坏绕文本,这里:

一、构造函数多了一个 colors数组,它由文本拆分后的数组迭代而来,里面储存的随机颜色对应于每一个文本个体;

二、添加一个渲染函数 render() ,通过调用请求关键帧动画API requestAnimationFrame() 每一次屏幕刷新给角度变量 deg 加上0.5 度,度数的变化在360度范围内循环。该函数利用角度的变化不断绘制相同的文本,形成文本旋转的效果。

红影 发表于 2024-5-14 21:29

代码里还给文字添加个边框,可以看出和边界的关系了呢{:4_204:}

红影 发表于 2024-5-14 21:30

这个转动的还能做到随机色,太厉害了{:4_199:}
如果是纯色的,就不需要这么麻烦了吧。

马黑黑 发表于 2024-5-14 21:30

红影 发表于 2024-5-14 21:30
这个转动的还能做到随机色,太厉害了
如果是纯色的,就不需要这么麻烦了吧。

少一行代码而已

红影 发表于 2024-5-14 21:31

deg = (deg + 0.5) % 360; 可以调整速度,数字越小,速度越慢。

马黑黑 发表于 2024-5-14 21:31

红影 发表于 2024-5-14 21:29
代码里还给文字添加个边框,可以看出和边界的关系了呢

是的,不过一楼实例没有边框

马黑黑 发表于 2024-5-14 21:32

红影 发表于 2024-5-14 21:31
deg = (deg + 0.5) % 360; 可以调整速度,数字越小,速度越慢。

是的

南无月 发表于 2024-5-14 21:38

下午在想这些字明天会动起来吧。。原来12小时不到。。{:4_170:}

马黑黑 发表于 2024-5-14 21:39

南无月 发表于 2024-5-14 21:38
下午在想这些字明天会动起来吧。。原来12小时不到。。

这个哪里需要那么多时间?关键是想不想做

红影 发表于 2024-5-14 21:48

马黑黑 发表于 2024-5-14 21:30
少一行代码而已

只多一行代码,就能随机色,厉害{:4_199:}

红影 发表于 2024-5-14 21:48

马黑黑 发表于 2024-5-14 21:31
是的,不过一楼实例没有边框

是的,我去试了代码才看到边框的{:4_173:}

红影 发表于 2024-5-14 21:49

马黑黑 发表于 2024-5-14 21:32
是的

这个速度也去试了验证了一下{:4_187:}

南无月 发表于 2024-5-14 21:49

马黑黑 发表于 2024-5-14 21:39
这个哪里需要那么多时间?关键是想不想做

看了一会挺好玩,字变大小,加字减字,变快变慢,改颜色,改位置,变圆,竖椭圆都可以。。{:4_170:}

这个好灵活啊。。跑得很流畅,看着很治愈

南无月 发表于 2024-5-14 22:04

马黑黑 发表于 2024-5-14 21:39
这个哪里需要那么多时间?关键是想不想做

从想法到实现,你给修了一条高速路的节奏{:4_170:}

马黑黑 发表于 2024-5-14 22:55

南无月 发表于 2024-5-14 22:04
从想法到实现,你给修了一条高速路的节奏

木有钱钱买高铁票

马黑黑 发表于 2024-5-14 23:08

南无月 发表于 2024-5-14 21:49
看了一会挺好玩,字变大小,加字减字,变快变慢,改颜色,改位置,变圆,竖椭圆都可以。。

...

多看免疫力会更强,刀子嗓会不治而愈

马黑黑 发表于 2024-5-14 23:09

红影 发表于 2024-5-14 21:49
这个速度也去试了验证了一下

速度合适就好

马黑黑 发表于 2024-5-14 23:10

红影 发表于 2024-5-14 21:48
只多一行代码,就能随机色,厉害

16进制随机颜色不久一行代码就可以实现的吗?

还有 rgb 随机颜色,也可以一行代码实现;hsl 也行。明天有空我试试。

南无月 发表于 2024-5-15 17:27

马黑黑 发表于 2024-5-14 22:55
木有钱钱买高铁票

自己修的高铁自家的和谐号不用票{:4_170:}
页: [1] 2 3 4
查看完整版本: canvas画布:绘制转动的椭圆形环绕文本