canvans绘制鼠标点击遍绘制一条直线,并支持撤销

7 篇文章 0 订阅
4 篇文章 0 订阅
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        body {
            margin: 0;
        }
        
        #canvas {
            border: 1px solid red;
        }
    </style>
</head>

<body>
    <div id="app">
        <canvas id="canvas" width="800" height="800" @click="main($event)"></canvas>
        <button id="undo" :disabled='prohibit' @click="redo">撤销</button>
        <button id="que" @click="determine">确定</button>
        <button class="clear" @click="clear">取消</button>
        <button class="draw" @click="draw($event)">绘制</button>
    </div>
</body>
<script src="./vue.js"></script>
<script src="./pako.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: "#app",
        data: {
            clicks: 0,
            lastClick: [0, 0],
            coordinateA: [],
            coordinateB: [],
            // 撤销的数组
            undoHistoryA: [],
            undoHistoryB: [],
            a: {},
            b: {},
            x: 0,
            y: 0,
            prohibit: true,
            chu: true,
        },
        watch: {

        },
        methods: {
            getCursorPosition(e) {
                if (e.pageX != undefined && e.pageY != undefined) {
                    var rect = canvas.getBoundingClientRect();
                    this.x = e.clientX - rect.left * (canvas.width / rect.width);
                    this.y = e.clientY - rect.top * (canvas.height / rect.height);
                } else {
                    this.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
                    this.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;

                }
                return [this.x, this.y];
            },
            drawLine(e) {
                var canvas = document.getElementById("canvas")
                context = canvas.getContext('2d');
                context.beginPath();
                this.x = this.getCursorPosition(e)[0]
                this.y = this.getCursorPosition(e)[1]
                if (this.chu == true) {
                    // 保存画布的像素数据
                    const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
                    const compressed = pako.deflate(new Uint8Array(imageData.data)); // 压缩,减小存储开销
                    this.undoHistoryA.push(compressed);
                    console.log(this.undoHistoryA.length, '刚开始存入的值')
                    this.chu = false
                }

                context.arc(this.x, this.y, 10, 0, 10 * Math.PI)
                context.stroke();

                if (this.clicks != 1) {
                    this.clicks++;

                } else {
                    // 不绘制, 只是将当前位置移动到新的目的坐标(x, y);
                    context.moveTo(this.lastClick[0], this.lastClick[1]);
                    // 不仅将当前位置移动到新的目标坐标(x,y),而且在两个坐标之间画一条直线。
                    context.lineTo(this.x, this.y, 6);
                    context.strokeStyle = '#000000';
                    context.stroke();
                    this.clicks = 0;
                }
                this.lastClick = [this.x, this.y];
                if (this.clicks == 0) {
                    const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
                    const compressed = pako.deflate(new Uint8Array(imageData.data)); // 压缩,减小存储开销
                    this.undoHistoryA.push(compressed);
                    this.prohibit = false

                    var x = this.x
                    var y = this.y
                    this.b = {
                        x,
                        y
                    }
                    this.coordinateB.push(this.b)

                } else {
                    var x = this.x
                    var y = this.y
                    this.a = {
                        x,
                        y
                    }
                    this.coordinateA.push(this.a)
                }


            },
            main(e) {
                this.drawLine(e)
            },
            redo() {
                // 撤销
                {
                    this.undoHistoryA.pop();
                    const compressed = this.undoHistoryA[this.undoHistoryA.length - 1]

                    //算法
                    this.coordinateA.pop()
                    this.coordinateB.pop()

                    try {
                        const decompressed = pako.inflate(compressed); // 解压
                        const uint8ClampedArray = new Uint8ClampedArray(decompressed);
                        const imageData = new ImageData(uint8ClampedArray, canvas.width, canvas.height);
                        context.putImageData(imageData, 0, 0);
                    } catch (error) {
                        console.error(error);
                    }
                    if (this.undoHistoryA.length === 0) {
                        this.prohibit = true;
                    }


                }
            },
            determine() {
                console.log(this.coordinateA, this.coordinateB, '坐标信息数组')
            },
            clear() {
                context.clearRect(0, 0, canvas.width, canvas.height);
            },
            draw(e) {
                this.main(e)
            }


        },
        mounted() {

        },
    })
</script>

</html>

</html>

</html>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值