キャンバスの実用化

目次

1.キャンバスサイン画板

1.1. エフェクト表示

1.2. コード分析

2. キャンバスは動的な時計を描画します

2.1. エフェクト表示

2.2. コード分析

1.キャンバスサイン画板

1.1. エフェクト表示

1.2. コード分析

<style>
        button.active {
            color: #fff;
            background-color: orange;
</style>
<body>
    <canvas id="MyCanvas" width="600" height="400"></canvas>
    <hr>
    <button id="boldBtn" type="button">粗线条</button>
    <button id="thinBtn" type="button">细线条</button>
    <button id="saveBtn" type="button">保存签名</button>
    <input type="color" id="color">
    <button class="clearBtn" type="button">橡皮擦</button>
    <button id="nullBtn" type="button">清空画布</button>
    <script>
        var canvas = document.getElementById("MyCanvas");
        var ctx = canvas.getContext("2d");
        ctx.lineJoin = 'round';//连接处圆润
        ctx.lineCap = 'round'//开端与终端圆润
        // 设置画笔粗细
        var boldBtn = document.querySelector("#boldBtn")
        var thinBtn = document.querySelector("#thinBtn")
        // 设置颜色
        var inputColor = document.querySelector("#color")
        // 保存签名
        var saveBtn = document.querySelector("#saveBtn")
        // 橡皮擦按钮
        var clearBtn = document.querySelector(".clearBtn")
        // 清空画布
        var nullBtn = document.querySelector("#nullBtn")
        // 设置允许绘制的变量
        var isDraw = false;
        // 鼠标按下开始画线
        canvas.onmousedown = function () {
            isDraw = true;
            ctx.beginPath();
            var x = event.pageX - canvas.offsetLeft;
            var y = event.pageY - canvas.offsetTop;
            ctx.moveTo(x, y)
        }
        // 鼠标抬起/离开,操作停止(防止画线操作粘连)
        canvas.onmouseleave = function () {
            isDraw = false;
            ctx.closePath()
        }
        canvas.onmouseup = function () {
            isDraw = false;
            ctx.closePath()
        }
        // 鼠标移动,继续画线
        canvas.onmousemove = function () {
            if (isDraw) {
                var x = event.pageX - canvas.offsetLeft;
                var y = event.pageY - canvas.offsetTop;
                ctx.lineTo(x, y);
                ctx.stroke()
            }
        }
        // 粗细画笔点击事件,线条宽度改变
        boldBtn.onclick = function () {
            ctx.globalCompositeOperation = 'source-over';
            ctx.lineWidth = 20;
            boldBtn.classList.add('active')
            thinBtn.classList.remove('active')
            clearBtn.classList.remove('active')
        }
        thinBtn.onclick = function () {
            ctx.globalCompositeOperation = 'source-over';
            ctx.lineWidth = 2;
            thinBtn.classList.add('active')
            boldBtn.classList.remove('active')
            clearBtn.classList.remove('active')
        }
        // 橡皮擦
        clearBtn.onclick = function () {
            ctx.globalCompositeOperation = 'destination-out';//合成模式(刮刮卡)
            ctx.lineWidth = 30;
            clearBtn.classList.add('active')
            boldBtn.classList.remove('active')
            thinBtn.classList.remove('active')
        }
        // 画布清除
        nullBtn.onclick = function () {
            ctx.clearRect(0, 0, 600, 400)
            nullBtn.classList.add('active')
        }
        // 保存
        saveBtn.onclick = function () {
            var urlData = canvas.toDataURL();
            var downloadA = document.createElement('a');
            downloadA.setAttribute('download', '酷炫签名');
            downloadA.href = urlData;
            downloadA.click()
            saveBtn.classList.add('active')
        }
        // 颜色设置
        inputColor.onchange = function () {
            ctx.strokeStyle = inputColor.value
        }
    </script>
</body>

概要:
(1) まず描画ボードを作成し、操作する要素を取得します。

(2) ブラシの太さと色を変更すると、コンソールに ctx を出力してその中の特定の属性を取得できます。クリック イベントがトリガーされたら、属性値を変更するだけです。

(3) 消しゴムは実際には要素の合成であり、古い要素の上に新しい要素を覆うだけです。

(4) キャンバスを直接クリアします。

(5) コンテンツの保存: toDataURL () メソッドは画像表示を含む データ URI を返しますが、これはキャンバスを画像に変換することに相当し、a タグ内にアドレスを入れてクリックすると画像ダウンロードと同様の効果が得られます。

2. キャンバスは動的な時計を描画します

2.1. エフェクト表示

2.2. コード分析

    <canvas id="MyCanvas" width="600" height="600"></canvas>
    <div class="timeClock">
        <span>当前时间:</span>
        <span class="hourbox"></span>&nbsp;
        <span class="minubox"></span>&nbsp;
        <span class="secondsbox"></span>
    </div>
    <script>
        var canvas = document.getElementById("MyCanvas");
        var ctx = canvas.getContext("2d");
        function render() {
            ctx.clearRect(0, 0, 600, 600)
            // 存档 保存当前坐标位置和上下文对象的状态
            ctx.save()
            ctx.translate(300, 300)
            ctx.rotate(-Math.PI / 2)
            ctx.save()
            for (var i = 0; i < 12; i++) {
                // 绘制小时的刻度
                ctx.beginPath();
                ctx.moveTo(170, 0);
                ctx.lineTo(190, 0);//画一条竖线(170-190)
                ctx.lineWidth = 8;
                ctx.strokeStyle = 'gray';
                ctx.stroke();
                ctx.closePath();
                ctx.rotate(2 * Math.PI / 12);//12个方向,旋转30度
            }
            ctx.restore()
            ctx.save()
            for (var i = 0; i < 60; i++) {
                // 绘制分钟的刻度
                ctx.beginPath();
                ctx.moveTo(180, 0);
                ctx.lineTo(190, 0);//画一条竖线(180-190)
                ctx.lineWidth = 2;
                ctx.strokeStyle = 'gray';
                ctx.stroke();
                ctx.closePath();
                ctx.rotate(2 * Math.PI / 60);//60个方向,旋转6度
            }
            ctx.restore()
            ctx.save()
            // 获取当前时间
            var time = new Date()
            var hour = time.getHours();
            var min = time.getMinutes();
            var sec = time.getSeconds();
            hour = hour >= 12 ? hour - 12 : hour;
            // 绘制秒针
            ctx.rotate(2 * Math.PI / 60 * sec)
            ctx.beginPath();
            ctx.moveTo(-30, 0);
            ctx.lineTo(190, 0);//画一条竖线(-30~190)
            ctx.lineWidth = 2;
            ctx.strokeStyle = 'red';
            ctx.stroke();
            ctx.closePath();
            ctx.restore()
            ctx.save()
            // 绘制分针
            ctx.rotate(2 * Math.PI / 60 * min + 2 * Math.PI / 60 / 60 * sec)
            ctx.beginPath();
            ctx.moveTo(-20, 0);
            ctx.lineTo(130, 0);//画一条竖线(-20~130)
            ctx.lineWidth = 5;
            ctx.strokeStyle = '#888';
            ctx.stroke();
            ctx.closePath();
            ctx.restore()
            ctx.save()
            // 绘制时针
            ctx.rotate(2 * Math.PI / 12 * hour + 2 * Math.PI / 12 / 60 * min + 2 * Math.PI / 12 / 60 / 60 * sec)
            ctx.beginPath();
            ctx.moveTo(-15, 0);
            ctx.lineTo(100, 0);//画一条竖线(-15~110)
            ctx.lineWidth = 7;
            ctx.strokeStyle = '#000';
            ctx.stroke();
            ctx.closePath();
            ctx.restore()

            ctx.restore()
            requestAnimationFrame(render);
            var box1 = document.querySelector(".hourbox")
            var box2 = document.querySelector(".minubox")
            var box3 = document.querySelector(".secondsbox")
            box1.innerHTML = `${hour}时`
            box2.innerHTML = `${min}分`
            box3.innerHTML = `${sec}秒`
        }
        render()
    </script>

  要約:

(1) 時計の目盛り: 12 時間 60 分 最初に垂直の短い線 [ moveToとlineToを組み合わせた] を描き、ループ内で対応する角度を回転 [回転] します。

(2) 現在時刻を取得 [ getHours , getMinutes , getSeconds ];

(3) 秒針、分針、時針を描画します。まず対応する時点を回転させてから、独自のスタイルで描画します (たとえば、秒針: 2 * Math.PI / 60 * sec===360/ ) 60 ※現在の秒値は秒針があるべき位置です)

(4) クロックを単独で実行させる: render関数を使用して、各実行前にキャンバスのclearRectをクリアします。

js や vue などの他の言語でも、同様の考え方で動的クロックを実装できます。

おすすめ

転載: blog.csdn.net/qq_44930306/article/details/132089611