Saber 酱的抱枕

Fly me to the moon

04/8
2017
学习

使用canvas将图片转换为base64编码

如果我们要在网页上处理图片,对于字符形式接收到的图片(比如用ajax获取的图片)可以将其转换为blob对象。但对于img标签(或通过new Image()对象获取的图片)来说,它们不是字符形式,而是html元素,不能转换成blob对象。

要使用这样的图片,我们可以先将图片绘制到canvas里,再使用canvas对象的toDataURL方法获取图片的base64编码(也就是data: URI)。

ps:blob对象和data: URI都可以用a标签的download属性来下载图片~

1.如下代码展示用image对象获取一张图片并转换为base64:

var dataURL="";
var Img = new Image();
Img.crossOrigin = "Anonymous";
Img.src="/f/head15.jpg";
Img.onload=function(){
	var canvas = document.createElement("canvas");
    canvas.width=Img.width;
    canvas.height=Img.height;
    canvas.getContext("2d").drawImage(Img,0,0,Img.width,Img.height); //将图片绘制到canvas中
    dataURL=canvas.toDataURL('image/png'); //转换图片为dataURL
};

注意image对象的crossOrigin 属性:

Img.crossOrigin = "Anonymous";

它在下面的情况中是有用的:
图片跨域了,但有个好消息是图片的服务器允许跨域。这时你加上这个crossOrigin属性就ok了,图片可以正常用。

但如果图片跨域了,并且图片的服务器【不允许】跨域,那你加上也没用,无解。

如果没解决跨域限制,canvas.toDataURL方法将报错,导致程序终止:

Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

2.如下代码展示从页面上的img标签获取图片内容,并将其转换为base64:

// 记得要在图片加载完成后执行
var image=document.querySelector("img"),
	canvas,
	dataURL;
image.onload=function () {
	canvas = document.createElement("canvas");
	canvas.width = image.width;
	canvas.height = image.height;
	canvas.getContext("2d").drawImage(image, 0, 0);
	dataURL=canvas.toDataURL('image/png'); //转换图片为dataURL
};

3.如果我们是要把图片用于下载的,那么对于色彩复杂、宽高较大的图片,用png格式显然体积会很大,可以转换成jpg的:

dataURL=canvas.toDataURL('image/jpeg',0.5);

经试验完全可用。另外chrome的话还可指定为 image/webp 。

参考资料来自MDN

4.扩展:现在各大浏览器只支持转换成png和jpeg格式,如果需要gif格式或bmp格式怎么办呢?可以用canvas2image.js

canvas2image支持将canvas里的图片数据转换为png、jpeg、gif、bmp格式,并可修改生成的图片的宽高。

你可以仅转换但不下载,也可直接下载。like this:

Canvas2Image.saveAsImage(canvasObj, width, height, type)
Canvas2Image.saveAsPNG(canvasObj, width, height)
Canvas2Image.saveAsJPEG(canvasObj, width, height)
Canvas2Image.saveAsGIF(canvasObj, width, height)
Canvas2Image.saveAsBMP(canvasObj, width, height)

Canvas2Image.convertToImage(canvasObj, width, height, type)
Canvas2Image.convertToPNG(canvasObj, width, height)
Canvas2Image.convertToJPEG(canvasObj, width, height)
Canvas2Image.convertToGIF(canvasObj, width, height)
Canvas2Image.convertToBMP(canvasObj, width, height)

使用canvas将图片转换为base64编码

07/11
2016
学习

HTML5中的跨文档消息传递

我们可以使用HTML5的postMessage()方法进行跨文档的消息传递,不会触发跨域问题。

例如,我们可以在父窗口中向iframe里的页面或通过window.open()打开的页面发送消息(不仅限于文本数据),这两个页面不必是同源的(跨域可以,不跨域也可以)都不会触发跨域问题。

例如我在当前页面加载了下面的iframe页面:

<iframe src="http://127.0.0.1/t/index.html" id="f1"></iframe>

我们想要向它发送消息,该怎么做呢?

想要实现通信,首先得在接收页面里添加对消息的处理功能。postMessage()发送到页面时会触发message事件,我们在子页面绑定这个事件:

window.addEventListener("message",function(event){
	if (event.origin == "http://www.saber.love"){//确保发送消息的域是已知的域
		alert(event.origin+"说:"+event.data);//处理接收到的数据
		// event.source.postMessage("Received!", "http://www.saber.love");//可选:向来源窗口发送回执
	}
},false);

这样当消息发送到子页面时,子页面就能够处理了。

当触发message事件时,有一些有用的信息:
event.origin:发送消息的文档所在的域;
event.data:postMessage()发送过来的消息;
event.source:发送消息的文档的window 对象的代理。

之后我们在父页面向子页面发送消息,代码如下:

var iframeWindow = document.getElementById("f1").contentWindow;
iframeWindow.postMessage("hello~", "http://127.0.0.1"); //第二个参数指定【接收方】必须是指定的域

子页面接收到消息后就会进行处理:

到这里一个简单的通信就完成了。

这个例子中的通信是单向的,如果要做成子页面也向父页面返回消息,那么父页面也得绑定message事件才行。

不过我有个疑惑,子窗口似乎不能主动用postMessage向父窗口发送消息。只能在接收消息后趁机发送吗?

HTML5中的跨文档消息传递

04/20
2016
学习

使用Access-Control-Allow-Origin解决Ajax跨域问题

跨域问题是web开发中一个常见的问题。例如说从网站a.com上用ajax把一些信息发送到b.com上,就会产生跨域问题。浏览器为了安全会阻止这个跨域请求,并产生一个跨域错误。

如果接收方b.com对应的文件是php文件,则可以在header函数中指定Access-Control-Allow-Origin的值,来设置哪些域名可以向这里发送跨域请求。

示例:

ajax请求如下(本彩笔使用了jq的ajax):

$.ajax({
    url:"http://127.0.0.1/t/t.php",
    type:"get",
    async:true,
    cache:false,
    dataType:"text",
    success:function  (data) {
        alert(data);
    }
});

php文件添加Access-Control-Allow-Origin头:

header("Access-Control-Allow-Origin:*"); // 允许指定域名发起的跨域请求
//header("Access-Control-Allow-Origin:http://tieba.baidu.com"); // 允许指定域名发起的跨域请求
echo "saber";

这就ok了。
Read More →

使用Access-Control-Allow-Origin解决Ajax跨域问题