canvas画布:绘制椭圆坏绕文本
<style>#mycanv { display: block; margin: 20px auto; }
.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; }
</style>
<h2>效果</h2>
<canvas id="mycanv" width="400" height="300"></canvas>
<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">"400"</span> height=<span class="tMagenta">"300"</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;</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"> };</cl-cd>
<cl-cd data-idx="12"> draw(context) {</cl-cd>
<cl-cd data-idx="13"> context.font = <span class="tMagenta">'bold 50px sans-serif'</span>;</cl-cd>
<cl-cd data-idx="14"> context.textAlign = <span class="tMagenta">'center'</span>;</cl-cd>
<cl-cd data-idx="15"> context.textBaseline = <span class="tMagenta">'middle'</span>;</cl-cd>
<cl-cd data-idx="16"> context.shadowOffsetX = -2;</cl-cd>
<cl-cd data-idx="17"> context.shadowOffsetY = 2;</cl-cd>
<cl-cd data-idx="18"> context.shadowColor = <span class="tMagenta">'#000'</span>;</cl-cd>
<cl-cd data-idx="19"> context.shadowBlur = 4;</cl-cd>
<cl-cd data-idx="20"> <span class="tBlue">var</span> a = 360 / <span class="tBlue">this</span>.chars.length, r1 = ww/2 - 60, r2 = hh/2 - 50;</cl-cd>
<cl-cd data-idx="21"> <span class="tBlue">this</span>.chars.forEach((<span class="tBlue">char</span>,key) => {</cl-cd>
<cl-cd data-idx="22"> <span class="tBlue">var</span> rad = (a * key - 90) * <span class="tRed">Math</span>.PI / 180;</cl-cd>
<cl-cd data-idx="23"> <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="24"> context.fillStyle = `#${<span class="tRed">Math</span>.random().toString(16).substr(2,6)}`;</cl-cd>
<cl-cd data-idx="25"> context.fillText(<span class="tBlue">char</span>, x, y);</cl-cd>
<cl-cd data-idx="26"> });</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"><span class="tBlue">var</span> cc = <span class="tBlue">new</span> ccText(<span class="tMagenta">'君不見黃河之水天上來'</span>);</cl-cd>
<cl-cd data-idx="31">cc.draw(ctx);</cl-cd>
<cl-cd data-idx="32"> </cl-cd>
<cl-cd data-idx="33"><<span class="tDarkRed">/script</span>></cl-cd>
</div>
<script>
var ww = mycanv.width, hh = mycanv.height;
var ctx = mycanv.getContext('2d');
class ccText {
constructor(text) {
this.chars = text.split('');
};
draw(context) {
context.font = 'bold 50px 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 - 60, r2 = hh/2 - 50;
this.chars.forEach((char,key) => {
var rad = (a * key - 90) * Math.PI / 180;
var x = ww/2 + r1 * Math.cos(rad), y = hh/2 + r2 * Math.sin(rad);
context.fillStyle = `#${Math.random().toString(16).substr(2,6)}`;
context.fillText(char, x, y);
});
};
};
var cc = new ccText('君不見黃河之水天上來');
cc.draw(ctx);
</script> 思路:
利用三角函数 cos 和 sin 计算出每一个字绕椭圆圆周布排的点XY坐标值,大圆半径 r1 和小圆半径 r2 的依据分别是画布宽高各半,宽高不同就会得出椭圆绕排效果,宽高相同则得到圆形绕排效果。
【注】第20行代码,r1 宽除以2减60、r2 高除以2减50,减去的数基于两个层面进行考虑:一是接近文本大小的值(50px,见第13行代码),二是此例中宽度大于高度。也可以减去相同的数值。 代码解释:
创建一个 ccText 类(代码8~28行),这个类通过构造函数(代码9~11行)将文本解析为数组,每一个数组元素包含一个字(字母)。
ccText 类有一个方法 draw(context)(代码12~27行),参数 context 指画笔。该方法:首先设置文本相关的属性(代码13~19行),有font设置、文本对齐设置、阴影设置等;接着,第20行代码,声明并计算平均角度 a、大圆半径 r1 和小圆半径 r2;然后,通过一个循环计算好每一个字的XY坐标点并将文字填充出来(代码在21~26行)。
关于圆周上XY坐标值的计算:
x = 圆心坐标x值 + 半径 * cos(弧度)
y = 圆心坐标y值 + 半径 * sin(弧度)
角度转弧度公式:
弧度 = 角度 * π / 180
第22行代码中,角度减去90是为了令第一个字位于最上方。原因:画布坐标系和HTML坐标系一样,0度指向3点钟方向,只有将其逆时针旋转90度,第一个字才会出现在圆周的顶点。 π 就是 PI,不要看成 n 画布的尺寸、文本的数量和字体的大小要配置得当,不然文字可能出现布局过于稀疏或彼此相互叠加的情况。 大概看了一下,画布时钟教程是基础
可以用时钟数字排列理解字的排列~~{:4_173:}
南无月 发表于 2024-5-14 18:10
大概看了一下,画布时钟教程是基础
可以用时钟数字排列理解字的排列~~
冰雪 马黑黑 发表于 2024-5-14 17:00
思路:
利用三角函数 cos 和 sin 计算出每一个字绕椭圆圆周布排的点XY坐标值,大圆半径 r1 和小圆半径 r ...
去试了一下,如果不减那个50,得到的文字只有一半了。其实减掉25就够用了吧{:4_173:} 这个还设置了阴影,还把第一个字细心地调到了最上面。很赞{:4_199:} 红影 发表于 2024-5-14 19:28
这个还设置了阴影,还把第一个字细心地调到了最上面。很赞
谢赞 红影 发表于 2024-5-14 19:24
去试了一下,如果不减那个50,得到的文字只有一半了。其实减掉25就够用了吧
你可以给画布一个 style 属性,领悟边界问题:
<canvas id="mycanv" width="400" height="300" style="border: 1px solid gray;"></canvas>
这是内联式CSS,用 style 属性来实现 马黑黑 发表于 2024-5-14 19:49
谢赞
不客气啊,整那么客气做什么{:4_173:} 马黑黑 发表于 2024-5-14 19:52
你可以给画布一个 style 属性,领悟边界问题:
嗯嗯,看到了{:4_187:} 红影 发表于 2024-5-14 21:20
嗯嗯,看到了
这个,做什么都可以,用边框观察边界 红影 发表于 2024-5-14 21:19
不客气啊,整那么客气做什么
不客气没有嘎嘎吃 马黑黑 发表于 2024-5-14 21:32
这个,做什么都可以,用边框观察边界
是的,下次吃不准的时候就可以加上这句了。 马黑黑 发表于 2024-5-14 21:32
不客气没有嘎嘎吃
那我选择不客气吧,我更喜欢吃素{:4_173:} 马黑黑 发表于 2024-5-14 18:45
冰雪
{:4_170:} 这个教程还没看,动态的就出来了。大白老师好速度 南无月 发表于 2024-5-14 21:51
这个教程还没看,动态的就出来了。大白老师好速度
哪里哪里 红影 发表于 2024-5-14 21:50
那我选择不客气吧,我更喜欢吃素
老吃素会脑萎缩