“Offer comes, ask friends to take it! I am participating in the 2022 Spring Recruit Punch card campaign. Click here for more details.”

Html2canvas was used in the project to take screenshots of the picture area. Since most of the pictures were in a few meters, the base64 was naturally larger than the original memory, so it needed to be optimized

1, the screenshot

The front-end screenshots are mostly html2Canavs.

There may be problems here

1.1. Image cross domain: it is possible that img does not set the Crossorigin attribute; Background may not allow cross-domain images, may be cache reasons;

Solutions:

  • The crossorigin attribute is set in the img element
  • Set the response header access-Control-allow-origin to Allow images to cross domains
  • To request image resources in JS mode, avoid caching. Set the URL with a timestamp, or set cache-control to no-cache in the HTTP header

1.2. Online pictures cannot be captured in screenshots:

Solutions:

A callback function called when a clone document is rendered that can be used to modify what is to be rendered without affecting the original source document.

For non-base64 image resources, switch to Base64 before proceeding to the next step

1.3. Blurred picture

Customize the canvas configuration options by setting the width and height of the canvas and then setting the width and height of the style

canvas.width = w * 2; canvas.height = h * 2; canvas.style.width = w + "px"; canvas.style.height = h + "px"; Context.scale (2,2); // then scale the canvas and double the size of the image onto the canvas.Copy the code

1.4. Image offset: Due to margin, the position of the generated image is offset

var canvas = document.createElement("canvas"); / / to get element relative to the Windows of the offset var. The rect = dom getBoundingClientRect (); var context = canvas.getContext("2d"); Context.translate (-rect.left,-rect.top); // Set the context position to a negative value of the offset relative to the window. // The actual offset will vary depending on the actual effectCopy the code

Please note: the actual offset position will be different according to the actual effect, the specific reason is not clear, I may be in the project because of the location of the drawing area, so the top has to be shifted 400 to the right to center

The complete code of the screenshot

const dom = document.getElementById('svg-container') const rect = dom.getBoundingClientRect() const can = document.createElement('canvas') const w = 1940 const h = 1080 can.width = w * 2; can.height = h * 2; can.style.width = w + "px"; can.style.height = h + "px"; Context.scale (2,2); // then scale the canvas and double the size of the image onto the canvas. const context = can.getContext('2d') context.translate(rect.left, rect.top html2canvas(dom, { canvas: can, scale: 2, onclone (html) { const imageNodes = $(html).find('#imageBg') const promises = [] imageNodes.each(function () { const element = $(this) const href = element.attr('href') if (href.startsWith('base64')) return const promise = new Promise((resolve, reject) => { const img = new Image() img.crossOrigin = 'anonymous' img.src = `${href}? time=${new Date().valueOf()}` img.onload = function () { const canvas = document.createElement('canvas') canvas.width = Canvas. height = naturalHeight // // const CTX = Canvas. getContext('2d') ctx.drawImage(img, 0, 0, naturalWidth, naturalHeight) const base64 = canvas.toDataURL('image/png') element.attr('href', base64) resolve() } img.onerror = reject }) promises.push(promise) }) return Promise.all(promises) }, backgroundColor: null }).then((canvas) => { })Copy the code

2. Base64 to BLOB

Specific code

Const getBlob = function (can) {let data = can.todataurl ('image/ PNG ', 1) data = data.split(',')[1] data = window.atob(data) const ia = new Uint8Array(data.length) for (let i = 0; i < data.length; i++) { ia[i] = data.charCodeAt(i) } return new Blob([ia], { type: 'image/ PNG '})} const blob = getBlob(canvas) const blobToFile = new window.file ([blob], this.currentImage.fileName, { type: 'image/*' })Copy the code

Instead of going bloB, you can also go file stream

Function base64ToBlob(dataurl) {var arr = dataurl.split(','), mime = arr[0].match(/ (.*?) ; /)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); }Copy the code

3, upload

Use axiOS form submission

Function (blob) {const uploadFileImg = function (blob) {const param = new FormData() Post (url, param, {headers: {' content-type ': 'multipart/form-data' } }).then((res) => { }, () => { }) }Copy the code

Conclusion:

Generally, screenshots are either downloaded or stored in base64 in the database, but image transfer to Base64 also brings memory problems and transmission problems, so the local selection of upload to obtain the server image resource address