Generally, teams will have a special domain name to place static resources, for example, Tencent is gtimg.com, Baidu is bdimg.com; or many teams use Tencent Cloud or Alibaba Cloud services.
The domain names of the main pages are often different. When it is necessary to perform getImageData() or toDataURL() operations on canvas images, cross-domain problems arise, and there are more than one level of cross-domain problems.
First, in the first step, the image server needs to configure Access-Control-Allow-Origin information, for example:
For example, PHP adds response header information, and the * wildcard indicates that any domain name is allowed:
header(Access-Control-Allow-Origin: *);
Or specify a domain name:
header(Access-Control-Allow-Origin: www.zhangxinxu.com);
At this point, the Chrome browser will no longer have Access-Control-Allow-Origin related error messages, but there will be other cross-domain error messages.
2. Canvas picture getImageData cross-origin cross-domain problemFor cross-domain images, as long as they can be displayed normally on the web page, they can be drawn using canvas's drawImage() API. But if you want to go one step further and obtain the complete pixel information of the image through the getImageData() method, you will probably make an error.
For example, use the following code to obtain your own avatar picture information on github:
var canvas = document.createElement('canvas');var context = canvas.getContext('2d');var img = new Image();img.onload = function () { context.drawImage(this, 0, 0) ; context.getImageData(0, 0, this.width, this.height);};img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4'';';
The result is the following error displayed under the Chrome browser:
Uncaught DOMException: Failed to execute 'getImageData ' on 'CanvasRenderingContext2D ': The canvas has been tainted by cross-origin data.
Firefox browser error is:
SecurityError: The operation is insecure.
If the canvas.toDataURL() method is used, it will report:
Failed to execute 'toDataURL ' on 'HTMLCanvasElement ': Tainted canvased may not be exported
The reasons are actually the same, caused by cross-domain.
So is there any way to solve this problem?
You can try the crossOrigin attribute.
3. HTML crossOrigin attribute solves cross-domain problem of resourcesIn HTML5, some elements provide attributes that support CORS (Cross-Origin Resource Sharing) (cross-origin resource sharing). These elements include <img>, <video>, <script>, etc., and the attribute name provided is the crossOrigin attribute. .
Therefore, the above cross-domain problem can be handled like this:
var canvas = document.createElement('canvas');var context = canvas.getContext('2d');var img = new Image();img.crossOrigin = '';img.onload = function () { context.drawImage (this, 0, 0); context.getImageData(0, 0, this.width, this.height);};img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';
Just add an img.crossOrigin = ''. Although the JS code here sets an empty string, the actual attribute value that works is anonymous.
crossOrigin can have the following two values:
Keywords | Definition |
---|---|
anonymous | Cross-origin resource requests for elements do not require the credentials flag to be set. |
use-credentials | Cross-domain resource requests for elements require the credentials flag to be set, meaning that credentials are required for the request. |
Among them, as long as the attribute value of crossOrigin is not use-credentials, everything will be parsed as anonymous, including empty strings, including characters like 'abc'.
For example:
img.crossOrigin = 'abc';console.log(img.crossOrigin); // The result is 'anonymous'
Another thing to note is that although there is no crossOrigin attribute, and setting crossOrigin=use-credentials will report a cross-domain error by default, they are different in nature. There is a big difference between the two.
crossOrigin compatibilityIE11+ (IE Edge), Safari, Chrome, and Firefox browsers all support it. IE9 and IE10 will report a SecurityError, as shown in the screenshot below:
4. Why can the crossOrigin attribute solve the problem of cross-domain resources?crossOrigin=anonymous Instead of telling the other server, you don't need to bring any non-anonymous information. For example, cookies, therefore, the current browser is definitely safe.
It's just like you want to go to someone's house to pick up a piece of clothing. crossOrigin=anonymous is different from telling the other person that I only want the clothes and nothing else. If you don't tell them, the other party may put a listening device or something in their clothes, which will be unsafe and the browser will block it.
5. What should I do if the IE10 browser does not support crossOrigin?When we request images, we do not directly use new Image(), but use ajax and the URL.createObjectURL() method to save the country.
The code is as follows:
var xhr = new XMLHttpRequest();xhr.onload = function () { var url = URL.createObjectURL(this.response); var img = new Image(); img.onload = function () { // At this point you You can use canvas to do whatever you want with img // ... code ... // Remember to release the memory after using the image URL.revokeObjectURL(url); }; img.src = url;};xhr.open('GET', url, true);xhr.responseType = 'blob';xhr.send();
This method is not only OK for the IE10 browser, but is also supported by all browsers that originally supported crossOrigin.
It only requires one more ajax request, which is fine!
According to practice, under IE browser, if the requested image is too large, a few thousand pixels, the image will fail to load. I guess it exceeds the blob size limit.
6. ConclusionI've learned a little experience at work recently, I hope it can help friends who encounter similar problems. I also hope that everyone will support VeVb Wulin Network.