马黑黑 发表于 2024-3-26 12:07

做一个canvas时钟(六)

本帖最后由 马黑黑 于 2024-3-26 12:09 编辑 <br /><br /><style>
.mama { font: normal 18px / 26px sans-serif; }
.mama p { margin: 12px 0; }
.mama mark { padding: 0 6px; background: lightblue; }

.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>到第五讲时,高颜值的时钟还不会走时,这是因为缺乏驱动。驱动将通过 requestAnimationFrame API 接口来实现。上一讲里,我们已经将画时钟的所有细节集中放到了一个函数里,函数名叫 render(),我们把 requestAnimationFrame(render)放入该函数内,函数自身只要从外部执行一次就会得到反复调用,直到手工停止它的执行或页面被关闭。代码结构如下:</p>

<div class='mum'>
<cl-cd data-idx="1"><span class="tGreen">//函数 :绘制时钟部件集合</span></cl-cd>
<cl-cd data-idx="2"><span class="tBlue">let</span> <span class="tRed">render</span> = () =&gt; {</cl-cd>
<cl-cd data-idx="3">&nbsp; &nbsp; <span class="tGreen">//这里是绘制时钟具体部件的代码集群</span></cl-cd>
<cl-cd data-idx="4">&nbsp; &nbsp; requestAnimationFrame(<span class="tRed">render</span>); <span class="tGreen">//请求关键帧动画从函数内部调用函数</span></cl-cd>
<cl-cd data-idx="5">};</cl-cd>
</div>

<p>requestAnimationFrame 其实也是一个定时器,它依据屏幕刷新率作为自己的执行频率,就是说,一秒钟里面它至少执行60次上下的任务,这取决于显示器的刷新频率的高低,频率越高,它执行任务的次数越多。</p>

<p>不过问题是,假如我们现在就将 requestAnimationFrame(render); 加入到函数 render() 中,情况和第五节的最终效果没什么两样,时钟还是没能走时。这又是为什么呢?请看三根指针的绘制代码:</p>

<div class='mum'>
<cl-cd data-idx="1">draw_rect(0, -3, 90, 6, 0, <span class="tMagenta">'lightgreen'</span>); <span class="tGreen">/* 时针 */</span></cl-cd>
<cl-cd data-idx="2">draw_rect(0, -2, 100, 4, 270 * <span class="tRed">Math</span>.PI/180, <span class="tMagenta">'lightgreen'</span>); <span class="tGreen">/* 分针 */</span></cl-cd>
<cl-cd data-idx="3">draw_rect(0, -1, 120, 2, 240 * <span class="tRed">Math</span>.PI/180, <span class="tMagenta">'lightgreen'</span>); <span class="tGreen">/* 秒针 */</span></cl-cd>
</div>

<p>以<span class="tRed">秒针</span>为例,它通过绘制矩形函数 draw_rect() 绘制出来,函数将画布坐标系移到了画布的中心,指针总是从圆心区域画起,向三点钟方向画一定宽高的矩形,requestAnimationFrame(render) 绘制秒钟就这么重复着画。要转动指针,实际上是转动画布坐标系,函数提供了一个 rad 参数,我们绘制的秒针传值是 240 * Math.PI/180 弧度,秒针定格在 11 点钟方向。这里,240是十一点钟方向的角度值,改变这个角度值,秒针的指向就会发生变化。所以,我们首先需要知道当下的秒数是多少,然后根据算法计算出这个秒数是多少度就可以将它替代 240 令秒针每一秒钟都指向正确的方向,秒钟就动起来了。</p>

<p>获得当下时间信息,需要用到JS的 Date 对象:通过声明一个变量将其实例化,就能从实例化变量中获得所需的年月日时分秒等具体时间信息:</p>

<div class='mum'>
<cl-cd data-idx="1"><span class="tGreen">// 将 <span class="tRed">Date</span> 对象实例化为 now</span></cl-cd>
<cl-cd data-idx="2"><span class="tBlue">let</span> now = <span class="tBlue">new</span> <span class="tRed">Date</span>();</cl-cd>
<cl-cd data-idx="3">&nbsp;</cl-cd>
<cl-cd data-idx="4"><span class="tGreen">// 从 now 实例化对象中获取时间信息</span></cl-cd>
<cl-cd data-idx="5"><span class="tBlue">let</span> year = now.getFullYear(); <span class="tGreen">//年</span></cl-cd>
<cl-cd data-idx="6"><span class="tBlue">let</span> month = now.getMonth() + 1; <span class="tGreen">//月 加1的原因:getMonth() 返回 0~11 的数值</span></cl-cd>
<cl-cd data-idx="7"><span class="tBlue">let</span> date = now.getDate(); <span class="tGreen">//日</span></cl-cd>
<cl-cd data-idx="8"><span class="tBlue">let</span> day = now.getDay(); <span class="tGreen">// 星期几(返回 0~6 的数值)</span></cl-cd>
<cl-cd data-idx="9"><span class="tBlue">let</span> hour = now.getHour(); <span class="tGreen">//小时</span></cl-cd>
<cl-cd data-idx="10"><span class="tBlue">let</span> minute = now.getMinute(); <span class="tGreen">//分钟</span></cl-cd>
<cl-cd data-idx="11"><span class="tBlue">let</span> second = now.getSecond(); <span class="tGreen">//秒钟</span></cl-cd>
<cl-cd data-idx="12"><span class="tBlue">let</span> msec = now.getMilliseconds(); <span class="tGreen">//毫秒</span></cl-cd>
</div>

<p>通过上面的时间信息获取方法,我们用 now.getSecond() 就能拿到当下的秒数。那么,秒数和角度又有什么关系呢?秒针指向刻度,而时钟上的每一个刻度向圆心的延长线都会和指向三点钟方向的X轴形成一定角度的夹角。理论上,每一秒钟的行进距离就是一个刻度的距离,亦即,它走的角度值为 6 度,那么,假设现在的秒数是 sec 秒,则角度为 sec * 6,为了精准,还需要考虑毫秒数,假设现在的毫秒数为 msec,依据毫秒和秒的关系,其所在度数为 msec * 0.36 / 1000,这个要加到秒钟的偏移度数中。我们来看代码:</p>

<div class='mum'>
<cl-cd data-idx="1"><span class="tGreen">/* 获取时间信息 */</span></cl-cd>
<cl-cd data-idx="2"><span class="tBlue">let</span> now = <span class="tBlue">new</span> <span class="tRed">Date</span>();</cl-cd>
<cl-cd data-idx="3">&nbsp;</cl-cd>
<cl-cd data-idx="4"><span class="tGreen">//获取秒数和毫秒数</span></cl-cd>
<cl-cd data-idx="5"><span class="tBlue">let</span> sec = now.getSeconds(),</cl-cd>
<cl-cd data-idx="6">&nbsp; &nbsp; msec = now.getMilliseconds();</cl-cd>
<cl-cd data-idx="7">&nbsp;</cl-cd>
<cl-cd data-idx="8"><span class="tGreen">//转换秒数毫秒数为角度</span></cl-cd>
<cl-cd data-idx="9"><span class="tBlue">let</span> sDeg = sec * 6 + (msec * 0.36 / 1000);</cl-cd>
<cl-cd data-idx="10">&nbsp;</cl-cd>
<cl-cd data-idx="11"><span class="tGreen">//绘制秒针</span></cl-cd>
<cl-cd data-idx="12">draw_rect(0, -1, 120, 2, (sDeg - 90) * <span class="tRed">Math</span>.PI/180, <span class="tMagenta">'lightgreen'</span>);</cl-cd>
</div>

<p>其他指针同理获得角度,然后将角度转换成弧度作为传参调用 draw_rect 依次绘制出来。这些,统统加入到 render() 函数中来,连同时钟的其他所有元素的具体绘制封装在一起,render() 内部在最后通过 requestAnimationFrame 按屏幕的刷新率去驱动时钟。时钟的最终效果以及全部代码如下,代码中,尤其需要注意对时间信息和时针转动角度的处理,这可是本讲的核心:</p>

<div style="margin-top: 20px; text-align: center;">
        <canvas id="canv" width="300" height="300"></canvas>
</div>
<p><br>全部代码:</p>

<div class='mum'>
<cl-cd data-idx="1">&lt;<span class="tDarkRed">div</span> style=<span class="tMagenta">"<span class="tBlue">margin-top:</span> 20px; <span class="tBlue">text-align:</span> center;"</span>&gt;</cl-cd>
<cl-cd data-idx="2">&nbsp; &nbsp; &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="3">&lt;<span class="tDarkRed">/div</span>&gt;</cl-cd>
<cl-cd data-idx="4"> </cl-cd>
<cl-cd data-idx="5">&lt;<span class="tDarkRed">script</span>&gt;</cl-cd>
<cl-cd data-idx="6">&nbsp;</cl-cd>
<cl-cd data-idx="7"><span class="tGreen">/* 获取画笔 */</span></cl-cd>
<cl-cd data-idx="8"><span class="tBlue">let</span> ctx = canv.getContext(<span class="tMagenta">'2d'</span>);</cl-cd>
<cl-cd data-idx="9">&nbsp;</cl-cd>
<cl-cd data-idx="10"><span class="tGreen">/* 函数 :绘制矩形(指针) */</span></cl-cd>
<cl-cd data-idx="11"><span class="tBlue">let</span> draw_rect = (x, y, w, h, rad, color) =&gt; {</cl-cd>
<cl-cd data-idx="12">    ctx.save();</cl-cd>
<cl-cd data-idx="13">    ctx.fillStyle = color;</cl-cd>
<cl-cd data-idx="14">    ctx.translate(150,150);</cl-cd>
<cl-cd data-idx="15">    ctx.rotate(rad);</cl-cd>
<cl-cd data-idx="16">    ctx.fillRect(x,y,w,h);</cl-cd>
<cl-cd data-idx="17">    ctx.restore();</cl-cd>
<cl-cd data-idx="18">};</cl-cd>
<cl-cd data-idx="19"><span class="tGreen">/* 函数 :绘制圆(环) */</span></cl-cd>
<cl-cd data-idx="20"><span class="tBlue">let</span> draw_circle = (x,y,r,lw,color1,color2) =&gt; {</cl-cd>
<cl-cd data-idx="21">    ctx.save();</cl-cd>
<cl-cd data-idx="22">    ctx.fillStyle = color1;</cl-cd>
<cl-cd data-idx="23">    ctx.strokeStyle = color2;</cl-cd>
<cl-cd data-idx="24">    ctx.lineWidth = lw;</cl-cd>
<cl-cd data-idx="25">    ctx.beginPath();</cl-cd>
<cl-cd data-idx="26">    ctx.arc(x,y,r,0,<span class="tRed">Math</span>.PI * 2);</cl-cd>
<cl-cd data-idx="27">    ctx.fill();</cl-cd>
<cl-cd data-idx="28">    ctx.stroke();</cl-cd>
<cl-cd data-idx="29">    ctx.restore();</cl-cd>
<cl-cd data-idx="30">};</cl-cd>
<cl-cd data-idx="31"><span class="tGreen">/* 函数 :绘制文本 */</span></cl-cd>
<cl-cd data-idx="32"><span class="tBlue">let</span> draw_text = (txt,x,y,color,fontsize=18,b=<span class="tMagenta">"bold"</span>) =&gt; {</cl-cd>
<cl-cd data-idx="33">&nbsp; &nbsp; ctx.save();</cl-cd>
<cl-cd data-idx="34">&nbsp; &nbsp; ctx.translate(150,150);</cl-cd>
<cl-cd data-idx="35">&nbsp; &nbsp; ctx.font = `${b} ${fontsize}px sans-serif`;</cl-cd>
<cl-cd data-idx="36">&nbsp; &nbsp; ctx.textAlign = <span class="tMagenta">'center'</span>;</cl-cd>
<cl-cd data-idx="37">&nbsp; &nbsp; ctx.textBaseline=<span class="tMagenta">"middle"</span>;</cl-cd>
<cl-cd data-idx="38">&nbsp; &nbsp; ctx.fillStyle = color;</cl-cd>
<cl-cd data-idx="39">&nbsp; &nbsp; ctx.fillText(txt,x,y);</cl-cd>
<cl-cd data-idx="40">&nbsp; &nbsp; ctx.restore();</cl-cd>
<cl-cd data-idx="41">};</cl-cd>
<cl-cd data-idx="42">&nbsp;</cl-cd>
<cl-cd data-idx="43"><span class="tBlue">let</span> render = () =&gt; {</cl-cd>
<cl-cd data-idx="44">&nbsp; &nbsp; <span class="tGreen">/* 获取时间 */</span></cl-cd>
<cl-cd data-idx="45">&nbsp; &nbsp; <span class="tBlue">let</span> now = <span class="tBlue">new</span> <span class="tRed">Date</span>();</cl-cd>
<cl-cd data-idx="46">&nbsp; &nbsp; <span class="tBlue">let</span> hr = now.getHours() &gt; 12 ? now.getHours() - 12&nbsp;: now.getHours(),</cl-cd>
<cl-cd data-idx="47">&nbsp; &nbsp; &nbsp; &nbsp; min = now.getMinutes(),</cl-cd>
<cl-cd data-idx="48">&nbsp; &nbsp; &nbsp; &nbsp; sec = now.getSeconds(),</cl-cd>
<cl-cd data-idx="49">&nbsp; &nbsp; &nbsp; &nbsp; msec = now.getMilliseconds();</cl-cd>
<cl-cd data-idx="50">&nbsp; &nbsp; <span class="tBlue">let</span> hDeg = hr * 30 + (min * 6 / 12),</cl-cd>
<cl-cd data-idx="51">&nbsp; &nbsp; &nbsp; &nbsp; mDeg = min * 6 + (sec * 6 / 60),</cl-cd>
<cl-cd data-idx="52">&nbsp; &nbsp; &nbsp; &nbsp; sDeg = sec * 6 + (msec * 0.36 / 1000);</cl-cd>
<cl-cd data-idx="53">&nbsp; &nbsp; </cl-cd>
<cl-cd data-idx="54">&nbsp; &nbsp; ctx.clearRect(0,0,300,300); <span class="tGreen">/* 每一次绘制前都衔擦除画布 */</span></cl-cd>
<cl-cd data-idx="55">&nbsp; &nbsp; draw_circle(150,150,140,10,<span class="tMagenta">'tan'</span>,<span class="tMagenta">'darkgreen'</span>); <span class="tGreen">/* 钟壳和钟面 */</span></cl-cd>
<cl-cd data-idx="56">&nbsp;</cl-cd>
<cl-cd data-idx="57">&nbsp; &nbsp; <span class="tGreen">/* 钟点 */</span></cl-cd>
<cl-cd data-idx="58">&nbsp; &nbsp; <span class="tBlue">for</span>(<span class="tBlue">let</span> i = 0; i &lt; 12; i ++) {</cl-cd>
<cl-cd data-idx="59">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">let</span> radian = <span class="tRed">Math</span>.PI/180*(i*30-60);</cl-cd>
<cl-cd data-idx="60">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">let</span> x = 115 * <span class="tRed">Math</span>.cos(radian), y = 115 * <span class="tRed">Math</span>.sin(radian);</cl-cd>
<cl-cd data-idx="61">&nbsp; &nbsp; &nbsp; &nbsp; draw_text(i+1, x, y, <span class="tMagenta">'green'</span>);</cl-cd>
<cl-cd data-idx="62">&nbsp; &nbsp; }</cl-cd>
<cl-cd data-idx="63">&nbsp; &nbsp; <span class="tGreen">/* 刻度 */</span></cl-cd>
<cl-cd data-idx="64">&nbsp; &nbsp; <span class="tBlue">for</span>(<span class="tBlue">let</span> i = 0; i &lt; 60; i ++) {</cl-cd>
<cl-cd data-idx="65">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">let</span> radian = <span class="tRed">Math</span>.PI/180*(i*6);</cl-cd>
<cl-cd data-idx="66">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">let</span> x = 150 + 130 * <span class="tRed">Math</span>.cos(radian), y = 150 + 130 * <span class="tRed">Math</span>.sin(radian);</cl-cd>
<cl-cd data-idx="67">&nbsp; &nbsp; &nbsp; &nbsp; draw_circle(x,y,1,2,<span class="tMagenta">'gray'</span>,<span class="tMagenta">'gray'</span>);</cl-cd>
<cl-cd data-idx="68">&nbsp; &nbsp; }</cl-cd>
<cl-cd data-idx="69">&nbsp; &nbsp; <span class="tGreen">/* 按一定次序绘制时钟各个元素 :确保指针、指针扣不会被遮挡 */</span></cl-cd>
<cl-cd data-idx="70">&nbsp; &nbsp; draw_text(`${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日`,0,-50,<span class="tMagenta">'white'</span>, 15, <span class="tMagenta">'normal'</span>); <span class="tGreen">/* 日期 */</span></cl-cd>
<cl-cd data-idx="71">&nbsp; &nbsp; draw_text(`星期${<span class="tMagenta">'日一二三四五六'</span>.substr(now.getDay(),1)}`,0,-25,<span class="tMagenta">'white'</span>, 15, <span class="tMagenta">'normal'</span>); <span class="tGreen">/* 星期 */</span></cl-cd>
<cl-cd data-idx="72">&nbsp; &nbsp; draw_text(<span class="tMagenta">'HUACHAO'</span>,0,60,<span class="tMagenta">'gray'</span>); <span class="tGreen">/* Logo */</span></cl-cd>
<cl-cd data-idx="73">&nbsp; &nbsp; draw_rect(0, -3, 90, 6, (hDeg - 90) * <span class="tRed">Math</span>.PI/180, <span class="tMagenta">'lightgreen'</span>); <span class="tGreen">/* 时针 */</span></cl-cd>
<cl-cd data-idx="74">&nbsp; &nbsp; draw_rect(0, -2, 100, 4, (mDeg - 90) * <span class="tRed">Math</span>.PI/180, <span class="tMagenta">'lightgreen'</span>); <span class="tGreen">/* 分针 */</span></cl-cd>
<cl-cd data-idx="75">&nbsp; &nbsp; draw_rect(0, -1, 120, 2, (sDeg - 90) * <span class="tRed">Math</span>.PI/180, <span class="tMagenta">'lightgreen'</span>); <span class="tGreen">/* 秒针 */</span></cl-cd>
<cl-cd data-idx="76">&nbsp; &nbsp; draw_circle(150,150,6,6,<span class="tMagenta">'white'</span>,<span class="tMagenta">'lightgreen'</span>); <span class="tGreen">/* 指针扣 */</span></cl-cd>
<cl-cd data-idx="77">&nbsp;</cl-cd>
<cl-cd data-idx="78">&nbsp; &nbsp; requestAnimationFrame(render);</cl-cd>
<cl-cd data-idx="79">};</cl-cd>
<cl-cd data-idx="80">&nbsp;</cl-cd>
<cl-cd data-idx="81">render();</cl-cd>
<cl-cd data-idx="82">&nbsp;</cl-cd>
<cl-cd data-idx="83">&lt;<span class="tDarkRed">/script</span>&gt;</cl-cd>
</div>

<p>《做一个canvas时钟》的课程至此结束。整体课程可能颇为抽象,尽管我已经极尽所能讲的很通俗了。时钟牵扯到的知识面很广,仅canvas画布的内容就相当不好理解,而且很多朋友此前对此没有什么基础。不过事在人为,能够消化这六个讲义,对提升编程水平和做帖能力等等都会有潜移默化的促进作用,甚至对改变自己的工作、学习和生活态度也会有正面的影响。谢谢大家!</p>

</div>

<script>

/* 获取画笔 */
let ctx = canv.getContext('2d');

/* 函数 :绘制矩形(指针) */
let draw_rect = (x, y, w, h, rad, color) => {
    ctx.save();
    ctx.fillStyle = color;
    ctx.translate(150,150);
    ctx.rotate(rad);
    ctx.fillRect(x,y,w,h);
    ctx.restore();
};
/* 函数 :绘制圆(环) */
let draw_circle = (x,y,r,lw,color1,color2) => {
    ctx.save();
    ctx.fillStyle = color1;
    ctx.strokeStyle = color2;
    ctx.lineWidth = lw;
    ctx.beginPath();
    ctx.arc(x,y,r,0,Math.PI * 2);
    ctx.fill();
    ctx.stroke();
    ctx.restore();
};
/* 函数 :绘制文本 */
let draw_text = (txt,x,y,color,fontsize=18,b="bold") => {
    ctx.save();
    ctx.translate(150,150);
    ctx.font = `${b} ${fontsize}px sans-serif`;
    ctx.textAlign = 'center';
    ctx.textBaseline="middle";
    ctx.fillStyle = color;
    ctx.fillText(txt,x,y);
    ctx.restore();
};

let render = () => {
    /* 获取时间 */
    let now = new Date();
    let hr = now.getHours() > 12 ? now.getHours() - 12 : now.getHours(),
      min = now.getMinutes(),
      sec = now.getSeconds(),
      msec = now.getMilliseconds();
    let hDeg = hr * 30 + (min * 6 / 12),
      mDeg = min * 6 + (sec * 6 / 60),
      sDeg = sec * 6 + (msec * 0.36 / 1000);
   
    ctx.clearRect(0,0,300,300); /* 每一次绘制前都衔擦除画布 */
    draw_circle(150,150,140,10,'tan','darkgreen'); /* 钟壳和钟面 */

    /* 钟点 */
    for(let i = 0; i < 12; i ++) {
      let radian = Math.PI/180*(i*30-60);
      let x = 115 * Math.cos(radian), y = 115 * Math.sin(radian);
      draw_text(i+1, x, y, 'green');
    }
    /* 刻度 */
    for(let i = 0; i < 60; i ++) {
      let radian = Math.PI/180*(i*6);
      let x = 150 + 130 * Math.cos(radian), y = 150 + 130 * Math.sin(radian);
      draw_circle(x,y,1,2,'gray','gray');
    }
    /* 按一定次序绘制时钟各个元素 :确保指针、指针扣不会被遮挡 */
    draw_text(`${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日`,0,-50,'white', 15, 'normal'); /* 日期 */
    draw_text(`星期${'日一二三四五六'.substr(now.getDay(),1)}`,0,-25,'white', 15, 'normal'); /* 星期 */
    draw_text('HUACHAO',0,60,'gray'); /* Logo */
    draw_rect(0, -3, 90, 6, (hDeg - 90) * Math.PI/180, 'lightgreen'); /* 时针 */
    draw_rect(0, -2, 100, 4, (mDeg - 90) * Math.PI/180, 'lightgreen'); /* 分针 */
    draw_rect(0, -1, 120, 2, (sDeg - 90) * Math.PI/180, 'lightgreen'); /* 秒针 */
    draw_circle(150,150,6,6,'white','lightgreen'); /* 指针扣 */

    requestAnimationFrame(render);
};

render();

</script>

流水光阴 发表于 2024-3-26 14:25

高手在花潮{:4_178:}

梦油 发表于 2024-3-26 16:16

真是很实用的制作啊。

马黑黑 发表于 2024-3-26 17:35

流水光阴 发表于 2024-3-26 14:25
高手在花潮

{:4_190:}

马黑黑 发表于 2024-3-26 17:36

梦油 发表于 2024-3-26 16:16
真是很实用的制作啊。

这个时钟还不错吧

南无月 发表于 2024-3-26 18:19

马黑黑 发表于 2024-3-26 17:36
这个时钟还不错吧

做贴者反馈,非常漂亮。。
使用实例在音画版,老师有空移步去瞧一眼。。

南无月 发表于 2024-3-26 18:20

教程后半段还没啃下来,晚上继续。{:4_170:}

马黑黑 发表于 2024-3-26 18:20

南无月 发表于 2024-3-26 18:20
教程后半段还没啃下来,晚上继续。

慢慢来不急。整体可能需要研究几次,最终可能可以发现讲义的错误

马黑黑 发表于 2024-3-26 18:21

南无月 发表于 2024-3-26 18:19
做贴者反馈,非常漂亮。。
使用实例在音画版,老师有空移步去瞧一眼。。

{:4_191:}

南无月 发表于 2024-3-26 20:24

马黑黑 发表于 2024-3-26 18:20
慢慢来不急。整体可能需要研究几次,最终可能可以发现讲义的错误


我不急的。。
教程多看几遍可以。。可我为啥要发现这个呢。。累呀累。。{:4_170:}

南无月 发表于 2024-3-26 20:25

马黑黑 发表于 2024-3-26 18:21


今天白的。。晚上真喝了几口,有点晕。{:4_170:}

绿叶清舟 发表于 2024-3-26 20:29

这个不能直接关联播放器吗

小辣椒 发表于 2024-3-26 20:34

黑黑的改进版时钟,发现现在这款时钟,应该是第三版吧,前年一个,去年一个,今年又一个了

马黑黑 发表于 2024-3-26 20:34

绿叶清舟 发表于 2024-3-26 20:29
这个不能直接关联播放器吗

为什么一定要关联音乐呢?制作成本太高赚不到钱钱的。看看 @南无月 肿么处理:

https://www.huachaowang.com/forum.php?mod=viewthread&tid=75123

马黑黑 发表于 2024-3-26 20:36

小辣椒 发表于 2024-3-26 20:34
黑黑的改进版时钟,发现现在这款时钟,应该是第三版吧,前年一个,去年一个,今年又一个了

不知道是什么版本,应该不是出口非洲的吧

小辣椒 发表于 2024-3-26 20:37

马黑黑 发表于 2024-3-26 20:36
不知道是什么版本,应该不是出口非洲的吧

因为我做过2个时钟的效果帖子,现在这个算上去就是三个了

马黑黑 发表于 2024-3-26 20:37

南无月 发表于 2024-3-26 20:25
今天白的。。晚上真喝了几口,有点晕。

晕晕更健康

绿叶清舟 发表于 2024-3-26 20:37

马黑黑 发表于 2024-3-26 20:34
为什么一定要关联音乐呢?制作成本太高赚不到钱钱的。看看 @南无月 肿么处理:

https://www.huachaowa ...

不加东西直接上去没反应啊,加了视频才行

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

绿叶清舟 发表于 2024-3-26 20:37
不加东西直接上去没反应啊,加了视频才行

该加啥加啥

马黑黑 发表于 2024-3-26 20:39

小辣椒 发表于 2024-3-26 20:37
因为我做过2个时钟的效果帖子,现在这个算上去就是三个了

那不止的
页: [1] 2 3 4
查看完整版本: 做一个canvas时钟(六)