马黑黑 发表于 2024-3-22 20:38

做一个canvas时钟(二)

<style>
.mama { font: normal 18px / 26px sans-serif; }
.mama p { margin: 12px 0; }
.mama mark { padding: 0 6px; background: lightblue; }
.wrap { margin: 20px auto 0; text-align: center; }
#canv, #canv1 { border: 1px solid gray; }

.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>

<div class="mama">

<p>要在canvas画布上作画,得先有笔。canvas画布提供两种画笔,2d和3d的,这两种笔一眼能瞧出它们的区别。3d笔太昂贵,咱老百姓消费不起,但有一个封装叫 three.js 可以启用3d绘画功能,并有OpenGL和WebGL加持,传说那个头叫轻量级,我瞅了瞅,1.7MB 大小,我勒了个去,这叫肥胖型苗条好不好!嗯,我们只用2d画笔,原生而且天生免费,比九块九包邮的更具魅力。</p>
<p>启用2d画笔,我们需要声明一下,用一个变量代表2d画笔,以后所有的画笔设置、绘制图形等操作都通过这支笔来完成。上一讲,我们的空白canvas画布有个id,id="canv",我们通过这个id就能轻松拿到2d画笔,一分钱也不用花费:</p>

<div class='mum'>
<cl-cd data-idx="1">&lt;<span class="tDarkRed">canvas</span> <span class="tRed">id</span>=<span class="tMagenta">"canv"</span> width=<span class="tMagenta">"300"</span> height=<span class="tMagenta">"300"</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>
<div class="tGreen"><cl-cd data-idx="4">    /* 获取画笔操作权限</cl-cd>
<cl-cd data-idx="5">    ctx 是2d画笔变量名(可以理解为画笔的姓名或别名,反正就是对画笔的一个称呼)</cl-cd>
<cl-cd data-idx="6">    canv 是canvas元素的<span class="tRed">id</span>名</cl-cd>
<cl-cd data-idx="7">    getContext()是获取canvas画布上下文相关的方法,有2d和3d两种模式</cl-cd>
<cl-cd data-idx="8">   声明 ctx 变量并获值后,一切绘画设置和操作将通过 ctx 完成</cl-cd>
<cl-cd data-idx="9">    */</cl-cd></div>
<cl-cd data-idx="10">    <span class="tBlue">let</span> ctx = canv.getContext(<span class="tMagenta">'2d'</span>);</cl-cd>
<cl-cd data-idx="11">&lt;<span class="tDarkRed">/script</span>&gt;</cl-cd>
</div>
<p>有了画笔,即使是一头大象,也可以开始作画了。不过大象主要用它自己的象鼻做画笔,只有在需要精致修饰处才用画笔,它的象鼻画笔也许是3d的,反正它可以恣意妄为,作品全都是抽象派风格的,最终作品可能连它自己都看不懂(不过据说它的老师能看得懂)。我们不,我们用性价比高到不能再高的2d画笔,按我们的构想和canvas相关语法规则去绘制现实主义作品,一切条缕清晰并富含思想。现在我们要绘制一个矩形,将来稍加改造说不准它可能就是我们美丽的时钟的指针:</p>
<div class='mum'>
<cl-cd data-idx="1">&lt;<span class="tDarkRed">canvas</span> <span class="tRed">id</span>=<span class="tMagenta">"canv"</span> width=<span class="tMagenta">"300"</span> height=<span class="tMagenta">"300"</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; &nbsp; <span class="tBlue">let</span> ctx = canv.getContext(<span class="tMagenta">'2d'</span>); <span class="tGreen">//画笔</span></cl-cd>
<cl-cd data-idx="5">&nbsp; &nbsp; ctx.fillStyle = <span class="tMagenta">'tan'</span>; <span class="tGreen">//画笔填充色</span></cl-cd>
<cl-cd data-idx="6">&nbsp; &nbsp; ctx.strokeStyle = <span class="tMagenta">'red'</span>; <span class="tGreen">//画笔描边色</span></cl-cd>
<cl-cd data-idx="7">&nbsp; &nbsp; ctx.lineWidth = 4; <span class="tGreen">//线条厚度(描边线)</span></cl-cd>
<cl-cd data-idx="8">&nbsp; &nbsp; ctx.strokeRect(10,10,100,20); <span class="tGreen">//绘制描边矩形</span></cl-cd>
<cl-cd data-idx="9">&nbsp; &nbsp; ctx.fillRect(10,10,100,20); <span class="tGreen">//绘制填充矩形</span></cl-cd>
<cl-cd data-idx="10">&lt;<span class="tDarkRed">/script</span>&gt;</cl-cd>
</div>

<p>效果如下。代码已有解释,随后我会更详细介绍一些要点:</p>
<div class="wrap"><canvas id="canv" width="300" height="300"></canvas></div>
<p>第5行代码,<span class="tRed">fillStyle</span> 是画笔的填充样式,用颜色赋值,可以是关键字(如 red)、十六进制(如 #333)、rgb、rgba、hsl、hsla 等等一切浏览器能够接受的颜色值。因为颜色值为字符串,所以用引号包裹起来。</p>
<p>第6行代码,<span class="tRed">strokeStyle</span>,定义画笔的描边颜色,规范与上行同,不同的是它是用来描边的。</p>
<p>第7行代码,<span class="tRed">lineWidth</span>,顾名思义,是线条的厚(宽)度,缺省且不进行填充时默认为2的效果,通常可根据需要对它进行设置。这个值会受到填充行为的影响,如果对矩形使用 fillRect 进行了填充,所设置的厚度会被挤占——实际上是被覆盖,上述代码其实是在相同的位置绘制了两个矩形,第一次用描边方式绘制,第二次用填充方式绘制,。</p>
<p>第8行代码,<span class="tRed">strokeRect</span> 是绘制描边矩形指令,使用 <span class="tRed">strokeStyle</span> 定义的描边色,缺省时默认黑色,需要四个参数,<mark>strokeRect(x,y,w,h);</mark> :</p>
<blockquote>① x : 水平方向起始坐标值(所画矩形的左边缘,相当于HTML元素的left);<br>② y : 垂直方向起始坐标值(所画矩形的上边,相当于HTML元素的上边);<br>③ w : 矩形宽度(width的缩写);<br>④ h : 矩形高度(height的缩写)</blockquote>
<p>代码第9行,<span class="tRed">fillRect</span>,绘制填充矩形,使用 <span class="tRed">fillStyle</span> 定义的填充色,默认黑色,所需参数和 <span class="tRed">strokeRect</span> 一样。</p>
<p>这些属性设定、图形绘制指令(方法),都很容易理解,前提是有一定的英文基础,没有的话查一下词典然后强记下来,同时特别需要注意写法,属性和指令的组合词里,第二个单词的头一个字母必须大写。</p>
<p>至此我们已经成功绘制了一个有描边色和填充色的矩形,但是,时钟的指针应该始于画布的正中央吧?这好办,绘制矩形 <mark>strokeRect(x,y,w,h);</mark> 时,我们把 x/y 的值都改一改,x 先为 150,y 为<mark>150-矩形高度的一半</mark>以确保垂直居中,代码为 <mark>ctx.strokeRect(150, 140, 100, 20);</mark>,矩形的位置不就合适了吗?请看:</p>
<div class="wrap"><canvas id="canv1" widt="300" height="300"></div>
<p>不过,上面画布中的矩形现在看上去一点也不像是指针,没关系,它们会变得像指针的,只是现在还不是时候,还有一些重要的问题要处理,处理好后它们就是百分百的时钟指针。</p>

</div>

<script>
        let ctx = canv.getContext('2d'), ctx1 = canv1.getContext('2d');
        ctx.fillStyle = ctx1.fillStyle = 'tan';
        ctx.strokeStyle = ctx1.strokeStyle = 'red';
        ctx.lineWidth = ctx1.lineWidth = 4;
        ctx.strokeRect(10,10,100,20);
        ctx.fillRect(10,10,100,20);

        ctx1.save;
        ctx1.lineWidth = 1;
        ctx1.moveTo(149.5, 0);
        ctx1.lineTo(149.5, 300);
        ctx1.stroke();
        ctx1.moveTo(0, 149.5);
        ctx1.lineTo(300, 149.5);
        ctx1.stroke();
        ctx1.restore();
        ctx1.fillRect(150,140,100,20);
       
</script>

南无月 发表于 2024-3-22 21:13

strokeRect(x,y,w,h);
跟着画了一根针,学到这个x,y,w,h,生单词还是要背滴。。{:4_173:}

南无月 发表于 2024-3-22 21:16

《叶水相逢》里的出现2D,原来是画笔。。
中午看到的时候不明白,咋跟3D有点像呢。。{:4_173:}

马黑黑 发表于 2024-3-22 21:29

南无月 发表于 2024-3-22 21:16
《叶水相逢》里的出现2D,原来是画笔。。
中午看到的时候不明白,咋跟3D有点像呢。。

3d2d是有区别的

马黑黑 发表于 2024-3-22 21:30

南无月 发表于 2024-3-22 21:13
strokeRect(x,y,w,h);
跟着画了一根针,学到这个x,y,w,h,生单词还是要背滴。。
简简单单的单词呢,40%是幼儿园英语有的

千羽 发表于 2024-3-23 08:36

吃瓜群众乙来了{:4_173:}

千羽 发表于 2024-3-23 08:56

来回飘一下{:7_300:}

马黑黑 发表于 2024-3-23 10:36

千羽 发表于 2024-3-23 08:56
来回飘一下

不画两手?

马黑黑 发表于 2024-3-23 10:36

千羽 发表于 2024-3-23 08:36
吃瓜群众乙来了

丙呢?

南无月 发表于 2024-3-23 17:15

马黑黑 发表于 2024-3-22 21:29
3d2d是有区别的

现在知道了。。
之前见过的3d是粒子。。。
现在看到的2d是画笔。。{:4_173:}
根本不是一回事

南无月 发表于 2024-3-23 17:22

马黑黑 发表于 2024-3-22 21:30
简简单单的单词呢,40%是幼儿园英语有的

巨人和蚂蚁。。{:4_170:}

马黑黑 发表于 2024-3-23 18:09

南无月 发表于 2024-3-23 17:22
巨人和蚂蚁。。

差不多

马黑黑 发表于 2024-3-23 18:09

南无月 发表于 2024-3-23 17:15
现在知道了。。
之前见过的3d是粒子。。。
现在看到的2d是画笔。。


粒子也有2d的

绿叶清舟 发表于 2024-3-23 20:08

矩形的位置要计算的吧

马黑黑 发表于 2024-3-23 20:16

绿叶清舟 发表于 2024-3-23 20:08
矩形的位置要计算的吧

位置就像 left、top 一样,都要计算,但是,第三讲,我们采用了一种新方法,总是画位置基本一致的矩形

绿叶清舟 发表于 2024-3-23 20:35

马黑黑 发表于 2024-3-23 20:16
位置就像 left、top 一样,都要计算,但是,第三讲,我们采用了一种新方法,总是画位置基本一致的矩形

单个的计算容易,整个形状出来感觉就很难了

南无月 发表于 2024-3-23 21:38

马黑黑 发表于 2024-3-23 18:09
差不多

好哒。。差别太大了,小白背单词正常正常{:4_170:}

南无月 发表于 2024-3-23 21:39

马黑黑 发表于 2024-3-23 18:09
粒子也有2d的

{:4_173:}粒子一般都是2D的。。
粒子和画笔不搭,都叫这个也是好玩。。

马黑黑 发表于 2024-3-23 21:58

南无月 发表于 2024-3-23 21:39
粒子一般都是2D的。。
粒子和画笔不搭,都叫这个也是好玩。。

画布可以绘制粒子

南无月 发表于 2024-3-23 22:11

马黑黑 发表于 2024-3-23 21:58
画布可以绘制粒子

{:4_173:}先画完时钟这个再说粒子,还能画啥呀
页: [1] 2 3
查看完整版本: 做一个canvas时钟(二)