WangShuXian6 / blog

FE-BLOG
https://wangshuxian6.github.io/blog/
MIT License
45 stars 10 forks source link

Canvas #56

Open WangShuXian6 opened 5 years ago

WangShuXian6 commented 5 years ago

Canvas

Canvas 基本用法 https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Basic_usage

WangShuXian6 commented 5 years ago

CanvasRenderingContext2D.getImageData()

返回一个ImageData对象,用来描述canvas区域隐含的像素数据,这个区域通过矩形表示,起始点为(sx, sy)、宽为sw、高为sh

ImageData ctx.getImageData(sx, sy, sw, sh)

参数

sx 将要被提取的图像数据矩形区域的左上角 x 坐标。 sy 将要被提取的图像数据矩形区域的左上角 y 坐标。 sw 将要被提取的图像数据矩形区域的宽度。 sh 将要被提取的图像数据矩形区域的高度。

返回值 一个ImageData 对象,包含canvas给定的矩形图像数据

错误抛出 IndexSizeError

如果高度或者宽度变量为0,则抛出错误


getImageData()

<canvas id="canvas"></canvas>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.rect(10, 10, 100, 100);
ctx.fill();

console.log(ctx.getImageData(50, 50, 100, 100));
// ImageData { width: 100, height: 100, data: Uint8ClampedArray[40000] }

此画布的四个角落分别表示为(left, top), (left + width, top), (left, top + height), 以及(left + width, top + height)四个点。这些坐标点被设定为画布坐标空间元素。 任何在画布以外的元素都会被返回成一个透明黑的ImageData对像


ImageData 对象

https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas

canvas对象真实的像素数据

只读属性 width 图片宽度,单位是像素 height 图片高度,单位是像素 data Uint8ClampedArray类型的一维数组,包含着RGBA格式的整型数据,范围在0至255之间(包括255)。

data属性返回一个 Uint8ClampedArray,它可以被使用作为查看初始像素数据。每个像素用4个1bytes值(按照红,绿,蓝和透明值的顺序; 这就是"RGBA"格式) 来代表。每个颜色值部份用0至255来代表。每个部份被分配到一个在数组内连续的索引,左上角像素的红色部份在数组的索引0位置。像素从左到右被处理,然后往下,遍历整个数组。

Uint8ClampedArray 包含高度 × 宽度 × 4 bytes数据,索引值从0到(高度×宽度×4)-1

读取图片中位于第50行,第200列的像素的蓝色部份


blueComponent = imageData.data[((50*(imageData.width*4)) + (200*4)) + 2]

let numBytes = imageData.data.length


***

>创建一个新的具体特定尺寸的ImageData对象。所有像素被预设为透明黑
```javascript
let myImageData = ctx.createImageData(width, height)

创建一个被anotherImageData对象指定的相同像素的ImageData对象。这个新的对象像素全部被预设为透明黑。这个并非复制了图片数据。

let myImageData = ctx.createImageData(anotherImageData)

putImageData() 方法对场景进行像素数据的写入

在场景内左上角绘制myImageData代表的图片

ctx.putImageData(myImageData, 0, 0)

保存图片

HTMLCanvasElement 提供一个toDataURL()方法,此方法在保存图片的时候非常有用。它返回一个包含被类型参数规定的图像表现格式的数据链接。返回的图片分辨率是96dpi。

canvas.toDataURL('image/png') 默认设定。创建一个PNG图片。 https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toDataURL

canvas.toDataURL('image/jpeg', quality) 创建一个JPG图片。你可以有选择地提供从0到1的品质量,1表示最好品质,0基本不被辨析但有比较小的文件大小。 https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toDataURL

当从画布中生成了一个数据链接,例如,你可以将它用于任何元素,或者将它放在一个有download属性的超链接里用于保存到本地。

也可以从画布中创建一个Blob对像。 canvas.toBlob(callback, type, encoderOptions) 这个创建了一个在画布中的代表图片的Blob对像。 https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toBlob


WangShuXian6 commented 5 years ago

颜色选择器

使用getImageData()去展示鼠标光标下的颜色。为此,我们要当前鼠标的位置,记为layerX和layerY,然后我们去查询getImageData()给我们提供的在那个位置的像数数组里面的像素数据。最后我们使用数组数据去设置背景颜色和

的文字去展示颜色值。

https://codepen.io/WangShuXian6/pen/ZmJBjd?editors=1010 default 图片如果跨域需要服务端设置允许

<canvas id="canvas"></canvas>
<div id="canvasr"></div>
let data='data:image/jpeg;base64,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'

let img = new Image()
img.crossOrigin = 'Anonymous'
//img.src = 'http://huaban.com/go/?pin_id=2120272012'
img.src=data
let canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')

img.onload = function() {
  ctx.drawImage(img, 0, 0)
  img.style.display = 'none'
}

let color = document.getElementById('canvasr')

function pick(event) {
  let x = event.layerX
  let y = event.layerY
  let pixel = ctx.getImageData(x, y, 1, 1)
  let data = pixel.data

  let rgba = 'rgba(' + data[0] + ',' + data[1] +
             ',' + data[2] + ',' + (data[3] / 255) + ')'

  color.style.background =  rgba
  color.textContent = rgba
  console.log(rgba)
}

canvas.addEventListener('mousemove', pick)
WangShuXian6 commented 5 years ago

图片灰度和反相颜色

在这个例子里,我们遍历所有像素以改变他们的数值。然后我们将被修改的像素数组通过putImageData()放回到画布中去。invert函数仅仅是去减掉颜色的最大色值255.grayscale函数仅仅是用红绿和蓝的平均值。你也可以用加权平均,例如x = 0.299r + 0.587g + 0.114b这个公式。更多资料请参考维基百科的Grayscale default 1 2

https://codepen.io/WangShuXian6/pen/NEvdPo

<canvas id='canvas'></canvas>
<button id='invertbtn'>invert</button>
<button id='grayscalebtn'>grayscale</button>

let data='data:image/jpeg;base64,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'

let img = new Image() img.src = data img.onload = function() { draw(this) }

function draw(img) { let canvas = document.getElementById('canvas') let ctx = canvas.getContext('2d') ctx.drawImage(img, 0, 0) img.style.display = 'none' let imageData = ctx.getImageData(0,0,canvas.width, canvas.height) let data = imageData.data

let invert = function() { // data 是对 imageData 的引用,故修改 data 会修改 imageData 的值 for (let i = 0; i < data.length; i += 4) { data[i] = 225 - data[i] // red data[i + 1] = 225 - data[i + 1] // green data[i + 2] = 225 - data[i + 2] // blue }

// 将修改后的 imageData 推入 ctx ctx.putImageData(imageData, 0, 0) }

let grayscale = function() { for (let i = 0; i < data.length; i += 4) { let avg = (data[i] + data[i +1] + data[i +2]) / 3 data[i] = avg // red data[i + 1] = avg // green data[i + 2] = avg // blue } ctx.putImageData(imageData, 0, 0) };

let invertbtn = document.getElementById('invertbtn') invertbtn.addEventListener('click', invert) let grayscalebtn = document.getElementById('grayscalebtn') grayscalebtn.addEventListener('click', grayscale) }

WangShuXian6 commented 5 years ago

使用 canvas 处理视频

https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Manipulating_video_using_canvas

WangShuXian6 commented 5 years ago

input 获取图片后 画在 canvas 上

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="file" name="image" id="file" accept="image/*" capture/>
<canvas id="canvas" width="300" height="400"></canvas>
<script>

    const imageInputWrapper = document.querySelector('#file')
    const initCanvas = document.querySelector('#canvas')
    const initCanvasCtx = initCanvas.getContext('2d')

    // const imageFileToBase64=(imageFile,callback)=>{
    //     let reader = new FileReader()
    //     reader.readAsDataURL(imageFile)
    //     reader.onload=(e)=>{
    //         const base64=e.target.result
    //         callback(base64)
    //     }
    // }

    // const loadImage=(imageSrc,callback)=>{
    //     let image = new Image()
    //     image.src = imageSrc
    //     image.onload=()=>{
    //         callback(image)
    //     }
    // }

    const drawWhiteCanvas=(initCanvasCtx)=>{
        initCanvasCtx.fillStyle='red'
        initCanvasCtx.fillRect(0, 0, 900,900)
    }

    // const drawImage=(initCanvasCtx,image)=>{
    //     initCanvasCtx,drawImage(image,0,0)
    // }

    imageInputWrapper.addEventListener('change', () => {
        console.log('imageInputWrapper--', imageInputWrapper.files[0])
        const imageFile = imageInputWrapper.files[0]
        drawWhiteCanvas(initCanvasCtx)

        let reader = new FileReader()
        reader.readAsDataURL(imageFile)
        reader.onload = (e) => {
            const base64 = e.target.result
            let image = new Image()
            image.src = base64
            image.onload = () => {
                console.log('image--', image)
                initCanvasCtx.drawImage(image, 0, 0, 200, 200);
            }
        }
    })

</script>
</body>
</html>
WangShuXian6 commented 5 years ago

选取图片后 再 经 canvas 处理后 最后由 PhotoClip 处理导出

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui"/>
    <title>PhotoClip</title>
    <style>
        body {
            margin: 0;
            text-align: center;
        }

        #clipArea {
            height: 300px;
        }

        #file,
        #clipBtn {
            margin: 20px;
        }

        #view {
            margin: 0 auto;
            width: 200px;
            height: 200px;
            background-color: #666;
        }

        #init-canvas{
            position: fixed;
            left: -100vw;
            bottom: -100vh;
            z-index: -100;
            opacity: 0;
        }
    </style>
</head>
<body ontouchstart="">

<div id="clipArea"></div>
<!--<input type="file" id="file">-->
<input type="file" name="image" id="file" accept="image/*" capture/>

<button id="clipBtn">截取</button>
<div id="view"></div>

<canvas id="init-canvas" width="500" height="500"></canvas>

<script src="js/hammer.min.js"></script>
<script src="js/iscroll-zoom-min.js"></script>
<script src="js/lrz.all.bundle.js"></script>

<script src="js/PhotoClip.js"></script>

<script>
    const imageInputWrapper = document.querySelector('#file')
    const initCanvas = document.querySelector('#init-canvas')
    const initCanvasCtx = initCanvas.getContext('2d')

    const drawWhiteCanvas = (initCanvasCtx) => {
        initCanvasCtx.fillStyle = 'red'
        initCanvasCtx.fillRect(0, 0, 900, 900)
    }

    imageInputWrapper.addEventListener('change', () => {
        console.log('imageInputWrapper--', imageInputWrapper.files[0])
        const imageFile = imageInputWrapper.files[0]
        drawWhiteCanvas(initCanvasCtx)

        let reader = new FileReader()
        reader.readAsDataURL(imageFile)
        reader.onload = (e) => {
            const base64 = e.target.result
            let image = new Image()
            image.src = base64
            image.onload = () => {
                const canvasWidth = initCanvas.width
                const canvasHeight = initCanvas.height
                const imageWidth = image.width
                const imageHeight = image.height

                let drawX
                let drawY
                let drawWidth
                let drawHeight

                if (imageWidth >= imageHeight) {
                    drawX = 0
                    drawY = (canvasHeight - imageHeight / imageWidth * canvasWidth) / 2
                    drawWidth = canvasWidth
                    drawHeight = imageHeight / imageWidth * canvasWidth
                } else {
                    drawX = (canvasWidth - imageWidth / imageHeight * canvasHeight) / 2
                    drawY = 0
                    drawWidth = imageWidth / imageHeight * canvasHeight
                    drawHeight = canvasHeight
                }

                initCanvasCtx.drawImage(image, drawX, drawY, drawWidth, drawHeight);

                const finalImage = initCanvas.toDataURL("image/jpeg", 1.0)
                initClip(finalImage)
            }
        }
    })

    const initClip = (img) => {
        let pc = new PhotoClip('#clipArea', {
            size: [260, 260],
            outputSize: 640,
            //adaptive: ['60%', '80%'],
            //file: '#file',
            img,
            view: '#view',
            ok: '#clipBtn',
            //img: 'img/mm.jpg',
            loadStart: function () {
                console.log('开始读取照片');
            },
            loadComplete: function () {
                console.log('照片读取完成');
            },
            done: function (dataURL) {
                console.log(dataURL);
            },
            fail: function (msg) {
                alert(msg);
            }
        });

        // 加载的图片必须要与本程序同源,否则无法截图
        pc.load(img);
    }
</script>
</body>
</html>
WangShuXian6 commented 5 years ago

图片始终显示完整的最长边

                const canvasWidth = initCanvas.width
                const canvasHeight = initCanvas.height
                const imageWidth = image.width
                const imageHeight = image.height

                let drawX
                let drawY
                let drawWidth
                let drawHeight

                if (imageWidth >= imageHeight) {
                    drawX = 0
                    drawY = (canvasHeight - imageHeight / imageWidth * canvasWidth) / 2
                    drawWidth = canvasWidth
                    drawHeight = imageHeight / imageWidth * canvasWidth
                } else {
                    drawX = (canvasWidth - imageWidth / imageHeight * canvasHeight) / 2
                    drawY = 0
                    drawWidth = imageWidth / imageHeight * canvasHeight
                    drawHeight = canvasHeight
                }

                initCanvasCtx.drawImage(image, drawX, drawY, drawWidth, drawHeight);
WangShuXian6 commented 5 years ago

触摸自由移动物体

index.html


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="./index.less">
<title>Title</title>
<meta name="viewport" content="width=device-width,height=device-height, user-scalable=no,initial-scale=1, minimum-scale=1, maximum-scale=1,target-densitydpi=device-dpi ">  <meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
</head>
<body>
<canvas width="500" height="1160" id="main-canvas"></canvas>


>index.js
```ts
const canvasEl =
    document.getElementById('main-canvas')
const ctx = canvasEl.getContext('2d')

const loadImage = (fn) => {
    const img = new Image();   // 创建img元素
    img.onload = () => {
        fn(img)
    }
    img.onerror = (error) => {
        console.error('error', error)
    }
    img.src = 'https://xxx.xxx.com/wsx/slideshow/horizontal/google-steve-irwins-57th/a_1.png'
}
//
// loadImage((img) => {
//     ctx.save()
//     ctx.translate(414, 0)
//     ctx.rotate(90 * Math.PI / 180)
//     ctx.drawImage(img, 0, 0, 1160, 500, 0, 0, 1160, 500)
//     ctx.restore()
// })

var previousTouchX
var previousTouchY
var step = 0
var img

const touchmove = (e) => {
    const touchX = e.changedTouches[0].clientX
    const touchY = e.changedTouches[0].clientY
    console.log('touchX', touchX)
    step += (touchX - previousTouchX)
    console.log('step', step)

    if (previousTouchX) {
        console.log('draw')
        ctx.clearRect(0, 0, 1160, 500)

        ctx.drawImage(img, 0, 0, 1160, 500, step, 0, 1160, 500)
    }

    previousTouchX = touchX
    previousTouchY = touchY
}

const touchstart = (e) => {
    previousTouchX = e.changedTouches[0].clientX
    previousTouchY = e.changedTouches[0].clientY
    console.log('start-touchX', previousTouchX)
}

loadImage((imgData) => {
    console.log('loaded')
    img = imgData
    ctx.drawImage(img, 0, 0, 1160, 500, step, 0, 1160, 500)
    canvasEl.addEventListener('touchstart', touchstart.bind(this), false)
    canvasEl.addEventListener('touchmove', touchmove.bind(this), false)
})
WangShuXian6 commented 5 years ago

canvas 点击判断

import {ArticlesCanvasInfo} from "@/config/canvas";

type ImageData = {
  data: Uint8ClampedArray,
  width: number,
  height: number
}

const calcDrawPos = (image: HTMLImageElement, canvasEl: HTMLCanvasElement) => {
  const imageWidth = image.width;
  const imageHeight = image.height;
  const canvasWidth = canvasEl.width;
  const canvasHeight = canvasEl.height;
  const imageRatio = imageWidth / imageHeight;
  const canvasRatio = canvasWidth / canvasHeight;

  if (imageRatio >= canvasRatio) {
    const scale = imageWidth / canvasWidth;
    const drawHeight = imageHeight / scale;
    const drawY = (canvasHeight - drawHeight) / 2;
    return {
      x: 0,
      y: drawY,
      width: canvasWidth,
      height: drawHeight
    };
  } else {
    const scale = imageHeight / canvasHeight;
    const drawWidth = imageWidth / scale;
    const drawX = (canvasWidth - drawWidth) / 2;
    return {
      x: drawX,
      y: 0,
      width: drawWidth,
      height: canvasHeight
    };
  }
};

export const drawToCanvas = (imgData, canvasEl?: HTMLCanvasElement): Promise<boolean> | boolean => {
  let currrentCanvasEl
  if (!canvasEl) {
    currrentCanvasEl = document.createElement('canvas')
  } else {
    currrentCanvasEl = canvasEl
  }

  if (!currrentCanvasEl) return false

  currrentCanvasEl.width = ArticlesCanvasInfo.width
  currrentCanvasEl.height = ArticlesCanvasInfo.height

  const ctx = currrentCanvasEl.getContext('2d');
  if (!ctx) {
    return false;
  }
  return new Promise((resolve) => {
    const img = new Image;
    img.src = imgData;
    img.crossOrigin = 'Anonymous';
    img.setAttribute('crossOrigin', 'Anonymous');
    img.onload = () => {
      //ctx.fillStyle = '#FFF';
      //ctx.fillRect(0, 0, ArticlesCanvasInfo.width, ArticlesCanvasInfo.height);
      const drawInfo = calcDrawPos(img, currrentCanvasEl);
      ctx.drawImage(img, 0, 0, img.width, img.height, drawInfo.x, drawInfo.y, drawInfo.width, drawInfo.height);
      // const strDataURI = currrentCanvasEl.toDataURL('image/jpeg', 0.5);
      resolve(true)
    };
  });
};

export const getDataURI = (imgData, canvasEl?: HTMLCanvasElement) => {
  let currrentCanvasEl
  if (!canvasEl) {
    currrentCanvasEl = document.createElement('canvas')
  } else {
    currrentCanvasEl = canvasEl
  }

  if (!currrentCanvasEl) return false

  currrentCanvasEl.width = ArticlesCanvasInfo.width
  currrentCanvasEl.height = ArticlesCanvasInfo.height

  const ctx = currrentCanvasEl.getContext('2d');
  if (!ctx) {
    return false;
  }
  return new Promise((resolve) => {
    const img = new Image;
    img.src = imgData;
    img.crossOrigin = 'Anonymous';
    img.setAttribute('crossOrigin', 'Anonymous');
    img.onload = () => {
      //ctx.fillStyle = '#FFF';
      //ctx.fillRect(0, 0, ArticlesCanvasInfo.width, ArticlesCanvasInfo.height);
      const drawInfo = calcDrawPos(img, currrentCanvasEl);
      ctx.drawImage(img, 0, 0, img.width, img.height, drawInfo.x, drawInfo.y, drawInfo.width, drawInfo.height);
      const strDataURI = currrentCanvasEl.toDataURL('image/jpeg', 0.5);
      resolve(strDataURI)
    };
  });
}

export const getCanvas = (imgData, canvasEl?: HTMLCanvasElement): Promise<HTMLCanvasElement> | false => {
  let currrentCanvasEl
  if (!canvasEl) {
    currrentCanvasEl = document.createElement('canvas')
  } else {
    currrentCanvasEl = canvasEl
  }

  if (!currrentCanvasEl) return false

  currrentCanvasEl.width = ArticlesCanvasInfo.width
  currrentCanvasEl.height = ArticlesCanvasInfo.height

  const ctx = currrentCanvasEl.getContext('2d');
  if (!ctx) {
    return false;
  }
  return new Promise((resolve) => {
    const img = new Image;
    img.src = imgData;
    img.crossOrigin = 'Anonymous';
    img.setAttribute('crossOrigin', 'Anonymous');
    img.onload = () => {
      //ctx.fillStyle = '#FFF';
      //ctx.fillRect(0, 0, ArticlesCanvasInfo.width, ArticlesCanvasInfo.height);
      const drawInfo = calcDrawPos(img, currrentCanvasEl);
      ctx.drawImage(img, 0, 0, img.width, img.height, drawInfo.x, drawInfo.y, drawInfo.width, drawInfo.height);
      // const strDataURI = currrentCanvasEl.toDataURL('image/jpeg', 0.5);
      resolve(currrentCanvasEl)
    };
  });
}

export const getImageData = (canvasEl: HTMLCanvasElement): ImageData | false => {
  if (!canvasEl) {
    console.warn('canvasEl 对象错误', canvasEl)
    return false
  }
  const {width, height} = canvasEl
  let ctx = canvasEl.getContext('2d')
  if (!ctx) {
    console.warn('ctx 对象错误', ctx)
    return false
  }
  return ctx.getImageData(0, 0, width, height)
}

export const getPixelSerialNumber = (clickX: number, clickY: number, canvasWidth: number = ArticlesCanvasInfo.width) => {
  return (clickY - 1) * canvasWidth + clickX
}

export const getPixelSerialAlpha = (Uint8ClampedArray: Uint8ClampedArray, pixelSerialNumber: number): number | false => {
  console.log('typeof pixelSerialNumber', typeof pixelSerialNumber)
  if (typeof pixelSerialNumber === 'number') {
    console.log('type number')
    const AlphaIndex = pixelSerialNumber * 4 + 3
    console.log('Uint8ClampedArray[AlphaIndex]', Uint8ClampedArray[AlphaIndex])
    return Uint8ClampedArray[AlphaIndex]
  } else {
    console.warn('pixelSerialNumber 不是数字:', pixelSerialNumber)
    return false
  }
}

// 要求,clickCanvasDom 与 checkedImage 宽高比相等,或者 以显示完整图片的策略在 canvas 上绘图
export const isClickImage = (clickCanvasDom: HTMLCanvasElement, checkedImage, e: MouseEvent): Promise<boolean> => {
  return new Promise(async (resolve) => {
    let x = e.pageX - clickCanvasDom.getBoundingClientRect().left
    let y = e.pageY - clickCanvasDom.getBoundingClientRect().top
    const pixelSerialNumber = getPixelSerialNumber(x, y)

    let checkedCanvasDom = await getCanvas(checkedImage)

    if (checkedCanvasDom instanceof HTMLCanvasElement) {
      let imageData = getImageData(checkedCanvasDom)
      if (!imageData) {
        resolve(false)
        return false
      } else {
        const pixelSerialAlpha = getPixelSerialAlpha(imageData.data, pixelSerialNumber)
        if (!pixelSerialAlpha)
          console.log('pixelSerialAlpha', pixelSerialAlpha)
        if (pixelSerialAlpha !== 0) {
          resolve(true)
          console.log('点击了图形')
        } else {
          resolve(false)
          console.log('点击了空白')
        }
      }
    } else {
      console.warn('canvasDom 不是 canvas 类型')
      resolve(false)
    }
  })

}
WangShuXian6 commented 5 years ago

svg 字符串转为 svg url

export const generateSvg = (svgString: string) => {
  let svg64 = btoa(svgString);
  var b64Start = 'data:image/svg+xml;base64,';
  let url= b64Start + svg64;
  return url
}