canvas 生成水印图片 加水印 剪切复制

vue3.0 图片裁剪 https://www.npmjs.com/package/vue-cropper
参考:https://juejin.cn/post/7316811315590135827

图片不清晰

poster(codeurl: any) {
    const query = wx.createSelectorQuery()
    query.select('#canvas')
      .fields({ node: true, size: true })
      .exec((res) => {
        const canvas = res[0].node

        const ctx = canvas.getContext('2d')
        // canvas.width = res[0].width
        // canvas.height = res[0].height
         const dpr = wx.getSystemInfoSync().pixelRatio
        canvas.width = res[0].width * dpr
        canvas.height = res[0].height * dpr
        this.Acanvas = canvas;
        this.width = res[0].width * dpr
        this.height = res[0].height* dpr;
        const img = canvas.createImage()
        img.onload = () => {
          ctx.drawImage(img, 0, 0, res[0].width* dpr, res[0].height* dpr)
          // 小程序码
          const img1 = canvas.createImage()
          img1.onload = () => {
          // ctx.drawImage(img1, rpx2px(128), rpx2px(560), rpx2px(142), rpx2px(142))
            ctx.drawImage(img1, rpx2px(125 * dpr), rpx2px(536 * dpr), rpx2px(125 * dpr), rpx2px(125 * dpr))
            ctx.scale(dpr,  dpr)
          }
          img1.src = codeurl
        }
        img.src = '../../images/poster.png'
      })
  },

html 加水印

加水印:https://zhuanlan.zhihu.com/p/111331319


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style type="text/css">
        #ReactApp {
            width: 400px;
            height: 400px;
            border: 1px solid #f00;
        }
    </style>
</head>

<body>
    <div id="ReactApp"></div>
    <script>
        const wrap = document.querySelector('#ReactApp');
        const { clientWidth, clientHeight } = wrap;
        const waterHeight = 120;
        const waterWidth = 180;
        // 计算个数
        const [columns, rows] = [~~(clientWidth / waterWidth), ~~(clientHeight / waterHeight)]
        for (let i = 0; i < columns; i++) {
            for (let j = 0; j <= rows; j++) {
                const waterDom = document.createElement('div');
                // 动态设置偏移值
                waterDom.setAttribute('style', `
            width: ${waterWidth}px; 
            height: ${waterHeight}px; 
            left: ${waterWidth + (i - 1) * waterWidth + 10}px;
            top: ${waterHeight + (j - 1) * waterHeight + 10}px;
            color: #000;
            position: absolute`
                );
                waterDom.innerText = '测试水印';
                wrap.appendChild(waterDom);
            }
        }
    </script>
</body>

</html>

中心旋转

           //---sample rotate  center
            var width  = 100
            var height = 100
            var x      = (canvas.width-width)*0.5	//形状放置在画布中心
            var y      = (canvas.height-height)*0.5	//形状放置在画布中心
            var cx     = x + 0.5 * width   			// cx 形状中心
            var cy     = y + 0.5 * height  			// cy 形状中心
			
			//--清空之前的绘制
			ctx.clearRect(0, 0, canvas.width, canvas.height)
			
            ctx.fillStyle = "#ff0000"
            ctx.fillRect(x, y, width, height)  			//没旋转之前的形状

            ctx.translate(cx, cy)              			//坐标圆点设置到形状中心
            ctx.rotate( (Math.PI / 180) * 45)  			//旋转 45 度
            ctx.translate(-cx, -cy)           			//坐标圆点重置到 0,0

            ctx.fillStyle = "#0000ff"
            ctx.fillRect(x, y, width, height)			//没旋转之后的形状


canvas 加水印

方式一


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body><script id="__bs_script__">//<![CDATA[
    document.write("<script async src='/browser-sync/browser-sync-client.js?v=2.26.7'><\/script>".replace("HOST", location.hostname));
//]]></script>

    <img id="img1" width="100" height="100" crossOrigin="anonymous" src="./1.png" alt="">
    <script>

        // 图片在前会 压在画片后面     ctx.beginPath() 回到最开始的状态 重新开辟路径


        class CanvasWay {
            constructor(watermark) {
                this.watermark = watermark
                const { width, height } = watermark
                this.canvas = document.createElement('canvas');
                this.canvas.setAttribute('width', width);
                this.canvas.setAttribute('height', height);
                this.R = Math.sqrt(width * width + height * height)

                // this.canvas.setAttribute('width', 2 * this.R);
                // this.canvas.setAttribute('height', 2 * this.R);
            }

            render() {
                const { txt, x, y, width, height, font, color, fontSize, alpha, angle } = this.watermark
                const ctx = this.canvas.getContext('2d');

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


                ctx.moveTo(0, 0); // 起点
                ctx.lineTo(0, 0 + height)

                ctx.lineTo(0 + width, 0 + height)
                ctx.lineTo(width + 0, 0)


                ctx.stroke();
                ctx.clip();

                // let oimg = document.getElementById('img1');
                // ctx.drawImage(oimg, 0, 0, oimg.width, oimg.height);
                let img = new Image()
                // img.setAttribute('crossOrigin', 'anonymous');
                img.crossOrigin = 'anonymous'
                img.src = './2.png'
                img.onload = () => {

                    ctx.beginPath();

                    ctx.textBaseline = 'top';
                    ctx.textAlign = 'left'
                    ctx.fillStyle = color;
                    ctx.globalAlpha = alpha;
                    ctx.font = `${fontSize}px ${font}`



                    const [columns, rows] = [~~(2 * this.R / (ctx.measureText(txt).width + 10)), ~~(2 * this.R / (fontSize + 10))];
                    // const [columns, rows] = [~~((height * Math.sin(Math.PI / 180 * angle) + width * Math.cos(Math.PI / 180 * angle)) / (ctx.measureText(txt).width + 10)), ~~((height * Math.cos(Math.PI / 180 * angle) + width * Math.sin(Math.PI / 180 * angle)) / (fontSize + 10))];

                    // ctx.translate(this.R, this.R)
                    ctx.rotate(-Math.PI / 180 * angle);
                    let zx = 0, zy = 0;
                    for (let i = 0; i < columns + 1; i++) {
                        for (let j = 0; j < rows + 1; j++) {

                            zx = x + i * (ctx.measureText(txt).width + 10)
                            zy = y + j * (fontSize + 10)

                            ctx.fillText(txt, zx - this.R, zy - this.R);


                        }
                    }

                    // ctx.translate(-this.R, -this.R)

                    // ctx.arc(0, 0, this.R, 0, 2 * Math.PI);//在canvas中绘制圆形

                    ctx.stroke()
                    ctx.rotate(Math.PI / 180 * angle);

                    // ctx.globalAlpha = 1;

                    ctx.drawImage(img, 0, 0, img.width / 6, img.height / 6);


                    let zimg = new Image()
                    zimg.src = this.canvas.toDataURL();
                    document.body.appendChild(zimg)

                }

            }
        }

        let vcanvas = new CanvasWay({
            width: 200,
            height: 300,
            txt: 'xx111',
            // x: 10,
            // y: 190,
            x: 0,
            y: 0,
            font: 'Arial',
            color: '#f00',
            fontSize: 16,
            alpha: 0.5,
            angle: -60

        })


        vcanvas.render()

        // setTimeout(() => {
        // let img = new Image()
        // img.src = vcanvas.render()
        // document.body.appendChild(img)
        // }, 1000)

    </script>
</body>

</html>

注意:ctx.translate(this.R, this.R) 移动是圆心,移动后,要进行还原 ctx.rotate(-Math.PI / 180 * angle); 以圆心为目标开始

方式二


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body><script id="__bs_script__">//<![CDATA[
    document.write("<script async src='/browser-sync/browser-sync-client.js?v=2.26.7'><\/script>".replace("HOST", location.hostname));
//]]></script>

    <img id="img1" width="100" height="100" crossOrigin="anonymous" src="./1.png" alt="">
    <script>

        // 图片在前会 压在画片后面     ctx.beginPath() 回到最开始的状态 重新开辟路径


        class CanvasWay {
            constructor(watermark) {
                this.watermark = watermark
                const { width, height } = watermark
                this.canvas = document.createElement('canvas');
                this.canvas.setAttribute('width', width);
                this.canvas.setAttribute('height', height);

                // this.canvas.setAttribute('width', 1000);
                // this.canvas.setAttribute('height', 1200);
            }

            render() {
                const { txt, x, y, width, height, font, color, fontSize, alpha, angle } = this.watermark
                const ctx = this.canvas.getContext('2d');

                ctx.clearRect(0, 0, width, height);
                // ctx.translate(100, 100)
                // ctx.moveTo(0, 0); // 起点
                // ctx.lineTo(0, height)

                // ctx.lineTo(width, height)
                // ctx.lineTo(width, 0)


                // ctx.stroke();



                ctx.beginPath();
                ctx.textBaseline = 'top';
                ctx.textAlign = 'left'
                ctx.fillStyle = color;
                ctx.globalAlpha = alpha;
                ctx.font = `${fontSize}px ${font}`

                ctx.rotate(Math.PI / 180 * angle);
                ctx.translate(0, -width * Math.sin(Math.PI / 180 * angle))
                // ctx.fillText(txt, x, y + fontSize);

                // 计算个数

                // const [columns, rows] = [~~(width / (ctx.measureText(txt).width + 10)), ~~(height / (fontSize + 10))];
                const [columns, rows] = [~~((height * Math.sin(Math.PI / 180 * angle) + width * Math.cos(Math.PI / 180 * angle)) / (ctx.measureText(txt).width + 10)), ~~((height * Math.cos(Math.PI / 180 * angle) + width * Math.sin(Math.PI / 180 * angle)) / (fontSize + 10))];


                let zx = 0, zy = 0;
                for (let i = 0; i < columns + 1; i++) {
                    for (let j = 0; j < rows + 1; j++) {
                        console.log(i, j)
                        zx = x + i * (ctx.measureText(txt).width + 10)
                        zy = y + j * (fontSize + 10)
                        ctx.fillText(txt, zx, zy);

                    }
                }

                ctx.translate(0, width * Math.sin(Math.PI / 180 * angle))
                ctx.rotate(-Math.PI / 180 * angle);
                ctx.globalAlpha = 1;


                // let oimg = document.getElementById('img1');
                // ctx.drawImage(oimg, 0, 0, oimg.width, oimg.height);
                let img = new Image()
                // img.setAttribute('crossOrigin', 'anonymous');
                img.crossOrigin = 'anonymous'
                img.src = './2.png'
                img.onload = () => {
                    ctx.drawImage(img, 0, 0, img.width / 6, img.height / 6);



                    // ctx.translate(-x, -y - fontSize)


                    let zimg = new Image()
                    zimg.src = this.canvas.toDataURL();
                    document.body.appendChild(zimg)

                }

            }
        }

        let vcanvas = new CanvasWay({
            width: 400,
            height: 600,
            txt: 'xx111',
            // x: 10,
            // y: 190,
            x: 0,
            y: 0,
            font: 'Arial',
            color: '#f00',
            fontSize: 16,
            alpha: 0.5,
            angle: 45

        })


        vcanvas.render()

        // setTimeout(() => {
        // let img = new Image()
        // img.src = vcanvas.render()
        // document.body.appendChild(img)
        // }, 1000)

    </script>
</body>

</html>

方式三


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <img id="img1" width="100" height="100" crossOrigin="anonymous" src="./1.png" alt="">
    <script>

        // 图片在前会 压在画片后面     ctx.beginPath() 回到最开始的状态 重新开辟路径


        class CanvasWay {
            constructor(watermark) {
                this.watermark = watermark
                const { width, height } = watermark
                this.canvas = document.createElement('canvas');
                // this.canvas.setAttribute('width', width);
                // this.canvas.setAttribute('height', height);
                this.R = Math.sqrt(width * width + height * height)

                this.canvas.setAttribute('width', 2 * this.R);
                this.canvas.setAttribute('height', 2 * this.R);
            }

            render() {
                const { txt, x, y, width, height, font, color, fontSize, alpha, angle } = this.watermark
                const ctx = this.canvas.getContext('2d');

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


                ctx.moveTo(this.R, this.R); // 起点
                ctx.lineTo(this.R, this.R + height)

                ctx.lineTo(this.R + width, this.R + height)
                ctx.lineTo(width + this.R, this.R)


                ctx.stroke();
                ctx.clip();

                // let oimg = document.getElementById('img1');
                // ctx.drawImage(oimg, 0, 0, oimg.width, oimg.height);
                let img = new Image()
                // img.setAttribute('crossOrigin', 'anonymous');
                img.crossOrigin = 'anonymous'
                img.src = './2.png'
                img.onload = () => {

                    ctx.beginPath();

                    ctx.textBaseline = 'top';
                    ctx.textAlign = 'left'
                    ctx.fillStyle = color;
                    ctx.globalAlpha = alpha;
                    ctx.font = `${fontSize}px ${font}`



                    const [columns, rows] = [~~(2 * this.R / (ctx.measureText(txt).width + 10)), ~~(2 * this.R / (fontSize + 10))];
                    // const [columns, rows] = [~~((height * Math.sin(Math.PI / 180 * angle) + width * Math.cos(Math.PI / 180 * angle)) / (ctx.measureText(txt).width + 10)), ~~((height * Math.cos(Math.PI / 180 * angle) + width * Math.sin(Math.PI / 180 * angle)) / (fontSize + 10))];

                    ctx.translate(this.R, this.R)
                    ctx.rotate(-Math.PI / 180 * angle);
                    let zx = 0, zy = 0;
                    for (let i = 0; i < columns + 1; i++) {
                        for (let j = 0; j < rows + 1; j++) {

                            zx = x + i * (ctx.measureText(txt).width + 10)
                            zy = y + j * (fontSize + 10)

                            ctx.fillText(txt, zx - this.R, zy - this.R);


                        }
                    }
                    ctx.rotate(Math.PI / 180 * angle);
                    ctx.translate(-this.R, -this.R)

                    // ctx.arc(this.R, this.R, this.R, 0, 2 * Math.PI);//在canvas中绘制圆形
                    ctx.stroke()
                    ctx.drawImage(img, this.R, this.R, img.width / 6, img.height / 6);


                    let copy = () => {
                        var imgData = ctx.getImageData(this.R, this.R, width, height);
                        // ctx.putImageData(imgData, 0, 0); 复制到其他地方
                        var canvas2 = document.createElement("canvas")
                        var cxt2 = canvas2.getContext("2d")
                        canvas2.width = width;
                        canvas2.height = height;
                        cxt2.putImageData(imgData, 0, 0, 0, 0, canvas2.width, canvas2.height)
                        var img2 = canvas2.toDataURL("image/png");
                        return img2
                    }



                    let zimg = new Image()
                    // zimg.src = this.canvas.toDataURL();
                    zimg.src = copy()
                    document.body.appendChild(zimg)

                }

            }
        }

        let vcanvas = new CanvasWay({
            width: 200,
            height: 300,
            txt: 'xx111',
            // x: 10,
            // y: 190,
            x: 0,
            y: 0,
            font: 'Arial',
            color: '#f00',
            fontSize: 16,
            alpha: 0.5,
            angle: 45

        })


        vcanvas.render()

        // setTimeout(() => {
        // let img = new Image()
        // img.src = vcanvas.render()
        // document.body.appendChild(img)
        // }, 1000)

    </script>
</body>

</html>

canvas特殊形状

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>绘制心形相框</title>
    <style>
        body { background: url("./images/bg3.jpg") repeat; }
        #canvas { border: 1px solid #aaaaaa; display: block; margin: 50px auto; }
    </style>
</head>
<body>
<div id="canvas-warp">
    <canvas id="canvas">
        你的浏览器居然不支持Canvas?!赶快换一个吧!!
    </canvas>
</div>

<script>
    window.onload = function(){
        var canvas = document.getElementById("canvas");
        canvas.width = 800;
        canvas.height = 600;
        var context = canvas.getContext("2d");
        context.fillStyle = "#FFF";
        context.fillRect(0,0,800,600);

        context.beginPath();
        context.moveTo(400,260);
        context.bezierCurveTo(450,220,450,300,400,315);
        context.bezierCurveTo(350,300,350,220,400,260);
        context.clip();
        context.closePath();

        var img = new Image();
        img.src = "./images/20-1.jpg";
        img.onload = function(){
            context.drawImage(img,348,240,100,100);
        }
    };
</script>
</body>
</html>

canvas镂空

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绘制其他剪纸图形</title>
</head>
<body>
<canvas id="canvas" width="600" height="400"></canvas>
</body>
<script>
    var canvas = document.getElementById('canvas'),
        context= canvas.getContext('2d');
    
    //Function……

    /**
     * 画网格
     */
    function drawGird(color,stepX,stepY) {
        context.strokeStyle = color;
        context.lineWidth = 0.5;

        for (var i = stepX + 0.5; i < context.canvas.width; i += stepX) {
            context.beginPath();
            context.moveTo(i, 0);
            context.lineTo(i, context.canvas.height);
            context.stroke();
        }

        for (var i = stepY + 0.5; i < context.canvas.height; i += stepY) {
            context.beginPath();
            context.moveTo(0, i);
            context.lineTo(context.canvas.width, i);
            context.stroke();
        }
    }
    
    function draw() {
        context.clearRect(0,0,canvas.width,canvas.height);
        drawGird('lightgray',10,10);
        
        context.save();
        
        context.shadowColor='rgba(200,200,0,0.5)';
        context.shadowOffsetX=12;
        context.shadowOffsetY=12;
        context.shadowBlur=15;
        
        drawCutouts();
        strokeCutoutShapes();
        context.restore();
    }

    /**
     * 画那些需要镂空的图形
     */
    function drawCutouts() {
        context.beginPath();
        addOuterRectanglePath();//CW,CW代表Clockwise顺时针

        addCirclePath();//CCW,CCW代表counter-clockwise逆时针
        addRectanglePath();//CCW
        addTrianglePath();//CCW

        context.fill();//Cut out shapes
    }

    /**
     * 镂空描边
     */
    function strokeCutoutShapes() {
        context.save();

        context.strokeStyle='rgba(0,0,0,0.7)';
        context.beginPath();
        addOuterRectanglePath();//CW
        context.stroke();

        context.beginPath();
        addCirclePath();
        addRectanglePath();
        addTrianglePath();
        context.stroke();
    }

    /**
     * 重写rect方法,增加了顺序和逆序路径的参数
     * @param x
     * @param y
     * @param w
     * @param h
     * @param direction 顺序和逆序,布尔类型
     */
    function rect(x,y,w,h,direction) {
        if(direction){//CCW
            context.moveTo(x,y);
            context.lineTo(x,y+h);
            context.lineTo(x+w,y+h);
            context.lineTo(x+w,y);
            context.closePath();
        }else{
            context.moveTo(x,y);
            context.lineTo(x + w, y);
            context.lineTo(x + w, y + h);
            context.lineTo(x, y + h);
            context.closePath();
        }
    }

    function addOuterRectanglePath() {
        context.rect(110, 25, 370, 335);
    }

    function addCirclePath() {
        context.arc(300,300,40,0,Math.PI*2,true);
    }

    function addRectanglePath() {
        rect(310,55,70,35,true);
    }

    function addTrianglePath() {
        context.moveTo(400,200);
        context.lineTo(250, 115);
        context.lineTo(200, 200);
        context.closePath();
    }

    //Init……
    context.fillStyle='goldenrod';
    draw();
</script>
</html>

canvas背景


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <canvas id="canvas" width="400" height="600"></canvas>
    <script>
        let canvas = document.getElementById("canvas")
        let context = canvas.getContext("2d")

        var fillImg = new Image();
        fillImg.src = '1.png';
        fillImg.onload = function () {
            context.fillStyle = context.createPattern(fillImg, 'repeat');
            context.fillRect(0, 0, 600, 600);
        }
    </script>
</body>

</html>

canvas 编译器

编译器oud.tencent.com/developer/article/1642243?from=14588

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web修理工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值