| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 | /** * Created by louizhai on 17/6/30. * description: Use canvas to draw. */function Draw(canvas, degree, config = {}) {  if (!(this instanceof Draw)) {    return new Draw(canvas, config);  }  if (!canvas) {    return;  }  let { width, height } = window.getComputedStyle(canvas, null);  // width = width.replace('px', '');  height = height.replace('px', '');  width = height.replace('px', '')*2;  this.canvas = canvas;  this.context = canvas.getContext('2d');  this.width = width;  this.height = height;  const context = this.context;  // 根据设备像素比优化canvas绘图  const devicePixelRatio = window.devicePixelRatio;  if (devicePixelRatio) {    canvas.style.width = `${width}px`;    canvas.style.height = `${height}px`;    canvas.height = height * devicePixelRatio;    canvas.width = width * devicePixelRatio;    context.scale(devicePixelRatio, devicePixelRatio);  } else {    canvas.width = width;    canvas.height = height;  }  context.lineWidth = 6;  context.strokeStyle = 'black';  context.lineCap = 'round';  context.lineJoin = 'round';  Object.assign(context, config);  const { left, top } = canvas.getBoundingClientRect();  const point = {};  const isMobile = /phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone/i.test(navigator.userAgent);  // 移动端性能太弱, 去掉模糊以提高手写渲染速度  if (!isMobile) {    context.shadowBlur = 1;    context.shadowColor = 'black';  }  let pressed = false;  const paint = (signal) => {    switch (signal) {      case 1:        context.beginPath();        context.moveTo(point.x, point.y);      case 2:        context.lineTo(point.x, point.y);        context.stroke();        break;      default:    }  };  const create = signal => (e) => {    e.preventDefault();    if (signal === 1) {      pressed = true;    }    if (signal === 1 || pressed) {      e = isMobile ? e.touches[0] : e;      point.x = e.clientX - left;      point.y = e.clientY - top;      paint(signal);    }  };  const start = create(1);  const move = create(2);  const requestAnimationFrame = window.requestAnimationFrame;  const optimizedMove = requestAnimationFrame ? (e) => {    requestAnimationFrame(() => {      move(e);    });  } : move;  if (isMobile) {    canvas.addEventListener('touchstart', start);    canvas.addEventListener('touchmove', optimizedMove);  } else {    canvas.addEventListener('mousedown', start);    canvas.addEventListener('mousemove', optimizedMove);    ['mouseup', 'mouseleave'].forEach((event) => {      canvas.addEventListener(event, () => {        pressed = false;      });    });  }  // 重置画布坐标系  if (typeof degree === 'number') {    this.degree = degree;    context.rotate((degree * Math.PI) / 180);    switch (degree) {      case -90:        context.translate(-height, 0);        break;      case 90:        context.translate(0, -width);        break;      case -180:      case 180:        context.translate(-width, -height);        break;      default:    }  }}Draw.prototype = {  scale(width, height, canvas = this.canvas) {    const w = canvas.width;    const h = canvas.height;    width = width || w;    height = height || h;    if (width !== w || height !== h) {      const tmpCanvas = document.createElement('canvas');      const tmpContext = tmpCanvas.getContext('2d');      tmpCanvas.width = width;      tmpCanvas.height = height;      tmpContext.drawImage(canvas, 0, 0, w, h, 0, 0, width, height);      canvas = tmpCanvas;    }    return canvas;  },  rotate(degree, image = this.canvas) {    degree = ~~degree;    if (degree !== 0) {      const maxDegree = 180;      const minDegree = -90;      if (degree > maxDegree) {        degree = maxDegree;      } else if (degree < minDegree) {        degree = minDegree;      }      const canvas = document.createElement('canvas');      const context = canvas.getContext('2d');      const height = image.height;      const width = image.width;      const degreePI = (degree * Math.PI) / 180;      switch (degree) {        // 逆时针旋转90°        case -90:          canvas.width = height;          canvas.height = width;          context.rotate(degreePI);          context.drawImage(image, -width, 0);          break;        // 顺时针旋转90°        case 90:          canvas.width = height;          canvas.height = width;          context.rotate(degreePI);          context.drawImage(image, 0, -height);          break;        // 顺时针旋转180°        case 180:          canvas.width = width;          canvas.height = height;          context.rotate(degreePI);          context.drawImage(image, -width, -height);          break;        default:      }      image = canvas;    }    return image;  },  getPNGImage(canvas = this.canvas) {    console.log(canvas.width, canvas.height);    return canvas.toDataURL('image/png');  },  getJPGImage(canvas = this.canvas) {    return canvas.toDataURL('image/jpeg', 0.5);  },  downloadPNGImage(image) {    const url = image.replace('image/png', 'image/octet-stream;Content-Disposition:attachment;filename=test.png');    window.location.href = url;  },  dataURLtoBlob(dataURL) {    const arr = dataURL.split(',');    const mime = arr[0].match(/:(.*?);/)[1];    const bStr = atob(arr[1]);    let n = bStr.length;    const u8arr = new Uint8Array(n);    while (n--) {      u8arr[n] = bStr.charCodeAt(n);    }    return new Blob([u8arr], { type: mime });  },  clear() {    let width;    let height;    switch (this.degree) {      case -90:      case 90:        width = this.height;        height = this.width;        break;      default:        width = this.width;        height = this.height;    }    this.context.clearRect(0, 0, width, height);  },  upload(blob, url, success, failure) {    const formData = new FormData();    const xhr = new XMLHttpRequest();    xhr.withCredentials = true;    formData.append('id', id);    formData.append('image', blob, 'sign');    xhr.open('POST', url, true);    xhr.setRequestHeader("x-csrf-token", csrf);    xhr.onload = () => {      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {        success(xhr.responseText);      } else {        failure();      }    };    xhr.onerror = (e) => {      if (typeof failure === 'function') {        failure(e);      } else {        console.log(`upload img error: ${e}`);      }    };    xhr.send(formData);  },};// export default Draw;
 |