html canvas 讓物體隨物體中心縮放


  在canvas的繪圖api中旋轉(rotate)與縮放(scale),如果直接調用的話是得不到想要的效果的,必須經過相應設置(偏移或其它)之后才能得到想要的效果。

  下面記錄一下canvas中隨物體中心縮放的處理。

 

  縮放的步驟:

    1.先執行縮放

    2.對畫布進行偏移(translate):

      x: - (物體中心(x軸) * (x軸的縮放值 - 1)) / x軸的縮放值

      y: - (物體中心 (y軸) * (y軸的縮放值 - 1)) / y軸的縮放值

    3. 進行普通的繪圖操作

  

 

具體實現:

html:

<canvas class="cv"></canvas>

javascript:

     let cv = document.querySelector('.cv'),
            ctx = cv.getContext('2d'),
            /*
            * @param Number sx 物體開始繪制的x點
            * @param Number sy 物體開始繪制的y點
            * @param Number width 物體開始繪制的寬
            * @param Number height 物體開始繪制的高
            */
            getCenter = (sx, sy, width, height) => { // 返回物體的中心點
                return {
                    x: sx + (width / 2),
                    y: sy + (height / 2)
                };
            },
            /*
            * 繪制圖形
            */
            draw = () => {
                let arc_x = 150, // 圓心x軸
                    arc_y = 150, // 圓心y軸
                    arc_r = 20, // 圓半徑
                    s = { // 縮放值
                        x: 2,
                        y: 2
                    },
                    arc_center = getCenter(arc_x - arc_r, arc_y - arc_r, 2 * arc_r, 2 * arc_r); // 圓心

                ctx.clearRect(0, 0, cv.width, cv.height);

                // 繪制圓
                ctx.save(); // 保存狀態,以免影響其它物體
                ctx.scale(s.x, s.y); // 執行縮放
                ctx.translate(- (arc_center.x * (s.x - 1)) / s.x, - (arc_center.y * (s.y - 1)) / s.y); // 縮放后的差偏移回來
                ctx.beginPath(); // 開啟路徑
                ctx.arc(arc_x, arc_y, arc_r, 0, 2 * Math.PI); // 繪制圓
                ctx.closePath(); // 關閉路徑
                ctx.stroke(); // 描邊繪制
                ctx.restore();// 恢復狀態
            };

        // 畫布大小
        cv.width = 800;
        cv.height = 500;
        draw(); // 開始繪制縮放

 

其它物體(圓、矩形、直線)的縮放的完整實現:

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <canvas class="cv"></canvas>

    <script type="text/javascript">
        let cv = document.querySelector('.cv'),
            ctx = cv.getContext('2d'),
            sv = 0, // 縮放的增加值
            speed = 0.01, // 縮放增加速度
            /*
            * @param Number sx 物體開始繪制的x點
            * @param Number sy 物體開始繪制的y點
            * @param Number width 物體開始繪制的寬
            * @param Number height 物體開始繪制的高
            */
            getCenter = (sx, sy, width, height) => { // 返回物體的中心點
                return {
                    x: sx + (width / 2),
                    y: sy + (height / 2)
                };
            },
            /*
            * 繪制圖形
            */
            draw = () => {
                let arc_x = 150, // 圓心x軸
                    arc_y = 150, // 圓心y軸
                    arc_r = 20, // 圓半徑
                    rect_x = 300, // 矩形x軸
                    rect_y = 100,// 矩形y軸
                    rect_width = 50,// 矩形的寬
                    rect_height = 50,// 矩形的高
                    line_sx = 500, // 直線起點x軸
                    line_sy = 100, // 直線起點y軸
                    line_ex = 600, // 直線終點x軸
                    line_ey = 210, // 直線終點y軸
                    s = { // 縮放值
                        x: 1 + sv,
                        y: 1 + sv
                    },
                    arc_center = getCenter(arc_x - arc_r, arc_y - arc_r, 2 * arc_r, 2 * arc_r), // 圓心
                    rect_center = getCenter(rect_x, rect_y, rect_width, rect_height), // 矩形中心
                    line_center = getCenter(line_sx, line_sy, line_ex - line_sx, line_ey - line_sy); // 直線中心

                ctx.clearRect(0, 0, cv.width, cv.height);

                // 繪制圓
                ctx.save(); // 保存狀態,以免影響其它物體
                ctx.scale(s.x, s.y); // 執行縮放
                ctx.translate(- (arc_center.x * (s.x - 1)) / s.x, - (arc_center.y * (s.y - 1)) / s.y); // 縮放后的差偏移回來
                ctx.beginPath(); // 開啟路徑
                ctx.arc(arc_x, arc_y, arc_r, 0, 2 * Math.PI); // 繪制圓
                ctx.closePath(); // 關閉路徑
                ctx.stroke(); // 描邊繪制
                ctx.restore();// 恢復狀態

                // 繪制矩形
                ctx.save();
                ctx.scale(s.x, s.y);
                ctx.translate(- (rect_center.x * (s.x - 1)) / s.x, - (rect_center.y * (s.y - 1)) / s.y);
                ctx.beginPath();
                ctx.strokeRect(rect_x, rect_y, rect_width, rect_height);
                ctx.closePath();
                ctx.restore();

                // 繪制直線
                ctx.save();
                ctx.scale(s.x, s.y);
                ctx.translate(- (line_center.x * (s.x - 1)) / s.x, - (line_center.y * (s.y - 1)) / s.y);
                ctx.beginPath();
                ctx.moveTo(line_sx, line_sy);
                ctx.lineTo(line_ex, line_ey);
                ctx.closePath();
                ctx.stroke();
                // 繪制線的外框,以便明顯線的縮放
                ctx.beginPath();
                ctx.strokeStyle = '#bbb';
                ctx.strokeRect(line_sx, line_sy, line_ex - line_sx, line_ey - line_sy);
                ctx.closePath();
                ctx.restore();

                sv += speed;

                if (sv <= 2) {
                    requestAnimationFrame(draw);
                }
            };

        // 畫布大小
        cv.width = 800;
        cv.height = 500;

        window.requestAnimationFrame = window.requestAnimationFrame
                                        || window.webkitRequestAnimationFrame
                                        || window.mozRequestAnimationFrame
                                        || window.oRequestAnimationFrame
                                        || window.msRequestAnimationFrame
                                        || function (callback) {
                                            callback && setTimeout(callback, 1000 / 60);
                                        };
        draw(); // 開始繪制縮放
    </script>
</body>
</html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM