Maison  >  Article  >  interface Web  >  Solutions aux problèmes de compatibilité utilisant canvas.toDataURL sous IE11

Solutions aux problèmes de compatibilité utilisant canvas.toDataURL sous IE11

php中世界最好的语言
php中世界最好的语言original
2018-04-14 14:12:506641parcourir

Cette fois, je vais vous apporter des idées pour résoudre le problème de compatibilité lié à l'utilisation de canvas.toDataURL dans IE11. Quelles sont les précautions pour résoudre le problème de compatibilité lié à l'utilisation de canvas.toDataURL dans IE11. combat réel Jetons un coup d'œil au cas.

Problème trouvé

Récemment, la méthode toDataURL de canvas a été utilisée dans le projet pour obtenir les données au format base64 de l'image pour le téléchargement en arrière-plan. Depuis que j'ai déjà rencontré le piège d'un canevas contaminé par des images inter-domaines et incapable d'obtenir des données, j'ai intelligemment ajouté la valeur de l'attribut crossOrigin depuis le début. Le code est à peu près le suivant :

<.>
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
const imageElement = document.createElement("img");
imageElement.crossOrigin = "Anonymous";
imageElement.onload = () => {
 context.drawImage(
 imageElement,
 params.left,
 params.top,
 canvas.width,
 canvas.height,
 0,
 0,
 canvas.width,
 canvas.height
 );
 const dataUrl = canvas.toDataURL("image/jpeg", 1);
}
imageElement.src = 'xxx';
Je pensais que c'était infaillible, et cela s'est très bien passé sur le navigateur Chrome, cependant, sur IE11, une SecurityError inexplicable s'est produite :

Solutions aux problèmes de compatibilité utilisant canvas.toDataURL sous IE11

Il n'y a pas de message d'erreur spécifique, seule la ligne d'exécution de toDataURL est localisée via l'invite, ce qui est vraiment déroutant.

Essayez

Je l'ai recherché sur Google pour la première fois et j'ai constaté que de nombreuses personnes ont rencontré ce problème, mais n'ont vu aucune solution efficace. Certaines personnes ont suggéré d'utiliser Fabric.js, mais après l'avoir examiné, elles ont pensé que c'était trop gênant. Sur caniuse, il est également clairement indiqué que cette méthode pose des problèmes sur IE11.

Cela semblait être un bug sur IE, alors j'ai pensé à un moyen de sauver le pays : il n'y a pas qu'une seule façon d'obtenir les données base64 de l'image Puisque la méthode toDataURL n'est pas bien supportée, utilisez une autre méthode :

    Convertissez d'abord le canevas en blob
  • Utilisez ensuite FileReader pour lire
  • sous la forme de dataUrl Le code est à peu près le suivant :

Cependant, cela ne sert à rien....
const reader = new FileReader();
reader.readAsDataURL(canvas.msToBlob());
reader.onloadend = () => {
 const base64data = reader.result;
};

Cette fois, c'était au tour de la méthode msToBlob de signaler une SecurityError. JE:? ? ?

Solution Il semble que cela puisse vraiment être une raison de sécurité. La seule raison de sécurité concerne les images inter-domaines. Je pensais que la politique de sécurité sur IE pourrait être plus stricte, et même si

est défini, les données ne sont toujours pas autorisées à être lues, alors j'ai pensé à une autre idée puisqu'il s'agit de plusieurs domaines, puis supprimez la croix. -facteur de domaine :

crossOrigin = "Anonymous"

    Utilisez ajax pour demander les données binaires de l'image
  • Convertir les données binaires au format base64
  • Définissez les données base64 obtenues comme src de l'élément d'image et dessinez-les sur la toile
  • Normalement, appelez toDataURL
Le code est à peu près le suivant :

Je l'ai essayé et j'ai atteint l'objectif avec succès.
// 之前的代码
// ...
// 最后一行 imageElement.src = 'xxx' 替换:
getDataUrlBySrc('xxx').then(b64 => (imageElement.src = b64));
function getDataUrlBySrc(src: string) {
 return new Promise<string>((resolve, reject) => {
 if (Cache.localGet("isIE")) {
  const xmlHTTP = new XMLHttpRequest();
  xmlHTTP.open("GET", src, true);
  // 以 ArrayBuffer 的形式返回数据
  xmlHTTP.responseType = "arraybuffer";
  xmlHTTP.onload = function(e) {
  
  // 1. 将返回的数据存储在一个 8 位无符号整数值的类型化数组里面
  const arr = new Uint8Array(xmlHTTP.response);
  
  // 2. 转为 charCode 字符串
  const raw = Array.prototype.map
   .call(arr, charCode => String.fromCharCode(charCode))
   .join("");
   
  // 3. 将二进制字符串转为 base64 编码的字符串
  const b64 = btoa(raw);
  
  const dataURL = "data:image/jpeg;base64," + b64;
  resolve(dataURL);
  };
  xmlHTTP.onerror = function(err) {
  reject(err);
  };
  xmlHTTP.send();
 } else {
  resolve(src);
 }
 });
}</string>

Plus tard, j'ai vérifié les informations et appris que si le canevas était contaminé, ni toDataURL ni toBlob ne seraient exécutés avec succès.

Défauts Bien que cette méthode puisse atteindre l’objectif, elle sacrifie les performances. Non seulement vous devez d'abord demander les données d'image, mais la conversion du codage des données prend également beaucoup de temps. Les petites images sont acceptables, mais si l'image est relativement grande, par exemple plus de 3M, l'ensemble du processus peut prendre jusqu'à une ou deux minutes, ce qui est inacceptable.

ToDataUrl du canevas compressera-t-il l'image ? Lorsque vous utilisez la méthode drawImage de Canvas pour dessiner un objet image sur le canevas, la taille de l'image augmentera considérablement et ne pourra être enregistrée qu'au format PNG.

Convertissez le canevas en base64 à l'aide de toDataUrl Même si encoderOptions est défini sur 1, l'image sera considérablement réduite, mais elle sera toujours plus grande que l'image d'origine. Si encoderOptions utilise la valeur par défaut de 0,92, la taille de l'image finale sera similaire à celle initiale

Je pense que vous maîtrisez la méthode après avoir lu le cas dans cet article. Pour des informations plus intéressantes, veuillez prêter attention aux autres éléments connexes. articles sur le site PHP chinois !

Lecture recommandée :

Comment utiliser l'entrée et la sortie Angular4

Méthode d'implémentation du chargement dynamique en cascade de la liste déroulante d'easyui (avec code)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn