canvas 从getImageData()跨域问题到同源策略再到node.js搭建本地服务器

场景

目前在看html5 canvas方面的知识,顺带敲一敲例子。学习到处理图片反色、蒙板的时候,需要用到getImageData()方法获取图片像素信息。而如果你的图片是来自本地,这个方法就会出现跨域问题。

关于getImageData()

在MDN中(
MDN/getImageData),我们可以看到,这个方法接收一个矩形区域起始点的坐标和宽高等4个参数,返回一个ImageData对象。这个对象中的data属性值是一个数组,每4项代表一个像素的rgba。
不过文档中并没有提到会产生跨域问题,那就来看看什么是跨域和同源策略。

同源策略

还是阅读MDN的文档
同源策略,可以看到

同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。

也就是说,同源策略是浏览器为了保护当前源的文档不被其他源恶意读写而使用的一个安全机制。但是,又有新的问题了:什么是源?

如果协议,端口(如果指定了一个)和域名对于两个页面是相同的,则两个页面具有相同的源。

原来,源就是协议、端口和域名的组合。如果两个页面的三要素中有一个不相同,那么这两个页面就是不同源的。当然IE的策略中并没有将端口当作策略的三要素,所以http://www.example.com/index.html和http://www.example.com:80/index.html在IE中属于同源。
所以,由于我们canvas的图片是保存在本地,浏览器认为与页面不同源,不能进行getImageData()操作。

解决方法

把图片放置在服务器中,通过服务器返回给客户端。

配置本地服务器

使用node.js配置本地服务器。

  1. 引入http、url、fs和past模块
var http = require('http');
var url = require('url');
var fs = require('fs');
var mine = require('./mine').types;
var path = require('path');

其中,mine.js是文件类型标识,即报文头部的content-type值。

exports.types = {
    "css": "text/css",
    "gif": "image/gif",
    "html": "text/html",
    "ico": "image/x-icon",
    "jpeg": "image/jpeg",
    "jpg": "image/jpeg",
    "js": "text/javascript",
    "json": "application/json",
    "pdf": "application/pdf",
    "png": "image/png",
    "svg": "image/svg+xml",
    "swf": "application/x-shockwave-flash",
    "tiff": "image/tiff",
    "txt": "text/plain",
    "wav": "audio/x-wav",
    "wma": "audio/x-ms-wma",
    "wmv": "video/x-ms-wmv",
    "xml": "text/xml"
  };

2.调用http.createServer()方法创建服务
3.获取url中的路径,并进行转码,防止其中包含中文字符无法解析

//获取路径名
  var pathname = url.parse(request.url).pathname;
  pathname = decodeURI(pathname);
  var realPath;

4.若路径为默认的host:port则跳转至默认路径

//设置默认路径
  if (pathname === '/') {
    realPath = path.join("asset/html/index.html", pathname);
  } else {
    realPath = path.join("asset", pathname);
  }

5.否则,获取目录中的文件后缀名,根据不同的后缀名返回不同的文件类型

//获取后缀名
  var ext = path.extname(realPath);
  ext = ext ? ext.slice(1) : 'unknown';
  fs.exists(realPath, function (exists) {
    //如果路径错误返回404
    if (!exists) {
      response.writeHead(404, {
        'Content-Type': 'text/plain'
      });

      response.write("This request URL " + pathname + " was not found on this server.");
      response.end();
    } else {
      fs.readFile(realPath, "binary", function (err, file) {
        if (err) {
          response.writeHead(500, {
            'Content-Type': 'text/plain'
          });
          response.end(err);
        } else {
          var contentType = mine[ext] || "text/plain";
          response.writeHead(200, {
            'Content-Type': contentType
          });
          response.write(file, "binary");
          response.end();
        }
      });
    }
  });

6.最后,监听端口。

文件目录


server.js放在根目录下,网页文件放在asset目录中。

git地址

css-demo
一个用来实践练习css属性的demo。

总结

只是想要实现一个图片反色的功能,却需要了解跨域、同源策略、node.js搭建服务器等知识。感觉有时候不能把自己局限在前端开发者的角色中,应该开阔视野,上升到程序员的高度来要求自己,多学习,多掌握技能才能提高自己。这一次,跨域部分我没有深入的去学习,以后会补充一篇博客来探讨跨域和解决跨域的几种方法,再深入学习ajax的原理和实现。

你可能感兴趣的:(前端HTML)