• Web API 97 0 1 发布

    DOM简介

    DOM(Document Object Model,文档对象模型)将XML/HTML文档构造成一个层次化的节点树,并提供了一系列的应用程序编程接口,以允许程序或脚本动态的访问和修改文档的内容、结构和样式。

    内容结构

    DOM由W3C进行了标准化,W3C DOM标准中立于平台和语言,分为以下3个部分:

    核心DOM:针对结构化文档的标准模型XML DOM: 针对XML文档的标注模型HTML DOM:针对HTML文档的标准模型 标准化历史

    DOM标准化的历史如下:

    规范化前版本  由各个浏览器自行实现,这个阶段的DOM经常被称为DHTML(Dynamic HTML,动态HTML)DOM级别1规范  发布于1998年10月1日,专注于HTML和XML文档模型DOM级别2规范  发布于2000年11月13日,对DOM级别1添加了样式表对象模型和事件处理模型DOM级别3规范  从2004年开始陆续发布,对DOM级别2作了系列扩展 核心DOM

    核心DOM定义了一个通用性的,以节点为基础的结构化文档模型,DOM文档模型中的所有内容都是节点,整个文档是一个文档根节点。

    基本属性

    节点的基本属性如下:

    nodeType  获取节点的类型。例如 1代表元素节点,2代表属性节点,3代表文本节点,通常这三类节点使用的最为普遍.nodeName  获取节点的名称。如果节点是元素节点,则 nodeName属性返回标签名;如果节点是属性节点,则nodeName属性返回属性的名称;其他节点类型,nodeName属性将返回不同节点类型的不同名称。nodeValue  设置或返回节点的值。如果节点是元素节点或文档节点,nodeValue属性值为null;如果节点是属性节点,nodeValue代表属性的值;如果节点是文本节点,nodeValue代表节点的内容;如果节点是注释节点,nodeValue代表注释的内容 节点类型

    核心DOM规范中定义了以下节点类型:

    类型说明Type值子节点Document(文档节点)表示整个文档(DOM树的根节点)9Element(max.one) ProcessingInstruction Comment DocumentTypeElement(元素节点)表示标签元素1Text ProcessingInstruction Comment CDATASection EntityReferenceAttribute(属性节点)表示元素的属性2Text EntityReferenceText(文本节点)表示元素或属性中的文本内容3无CDATASection(CDATA区段节点)表示文档中的 CDATA 区段4无DocumentFragment(文档片段节点)表示轻量级的Document 对象11Text ProcessingInstruction Comment CDATASection EntityReferenceComment(注释节点)表示注释8无

    其他还有几个,但一般不太用到,在此暂不列出。

    节点层次

    节点树中的节点彼此拥有层级关系:父节点(parent),子节点(child)和同胞节点(sibling)等。父节点拥有子节点,同级的子节点被称为同胞节点。 另外一部分节点如元素节点拥有属性节点. DOM规范为节点提供了以下诸多属性,以用于获取节点的层次关联信息。

    属性说明childNodes获取当前节点的所有子节点(※1)firstChild获取当前节点的第一个子节点(※1)lastChild获取当前节点的最后一个子节点(※1)ownerDocument获取该节点的文档根节点,相当与documentparentNode获取当前节点的父节点previousSibling获取当前节点的前一个同级节点nextSibling获取当前节点的后一个同级节点attributes获取当前元素节点的所有属性节点集合(※2)※1 部分类型的节点如文本节点等没有子节点.※2 仅部分类型的节点如元素节点拥有属性 创建节点 方法说明document.write()这个方法可以把任意字符串插入到文档中document.createElement()创建一个元素节点node.appendChild()将新节点追加到子节点列表的末尾document.createTextNode()创建一个文本节点node.insertBefore()将新节点插入在前面node.replaceChild()将新节点替换旧节点node.cloneNode()复制节点node.removeChild()移除节点 HTML DOM

    HTML DOM定义了一个HTML文档的文档对象模型。

    HTML文档首先是一个XML文档,为简单起见,XML DOM部分也包含在HTML DOM里一并说明。

    HTML文档的主要构成元素是各类HTML标签,HTML文档中的标签对应着元素节点。

    元素属性

    HTML元素的属性有attribute与property两个概念,这两个通常都被翻译成属性,但含义完全不一样。

    attribute是HTML标签属性,设计期在文档中直接记述,运行期可以通过Node的接口方法getAttribute(name)和setAttribute(name,value)进行访问。attribute值只存在文字列类型。而property是JS对象属性,运行期象一般的JS对象访问一样直接元素进行操作。property值拥有各自不同的数据类型。

    通常每个attribute都有一个同名的property,property可以看成是attribute的包装器,同时也对attribute值进行必要的类型转换。

    HTML: <input id="input1" type="checkbox" checked= "checked"/> <input id="input2" type="checkbox" checked= "true"/> JavaScript: console.log(document.getElementById("input1").getAttribute("checked")); // checked console.log(document.getElementById("input1").checked); // true console.log(document.getElementById("input2").getAttribute("checked"); // true 元素事件 事件阶段(Event Phases)

    当一个DOM事件被触发的时候,它并不只是在它的起源对象上触发一次,而是会经历以下三个不同的阶段:

    捕获阶段  事件的第一个阶段是捕获阶段。事件从文档的根节点出发,随着DOM树的结构向事件的目标节点流去。途中经过各个层次的DOM节点,并在各节点上触发捕获事件,直到到达事件的目标节点。捕获阶段的主要任务是建立传播路径,在冒泡阶段,事件会通过这个路径回溯到文档跟节点。目标阶段  捕获阶段结束,即当事件到达目标节点后,事件就进入了目标阶段,事件在目标节点上被触发。冒泡阶段  事件在目标元素上触发后,并不在这个元素上终止。它会随着DOM树一层层向上冒泡,直到到达最外层的根节点。 事件处理

    TODO:待编辑

    事件分类

    TODO:待编辑

    元素样式

    TODO:待编辑

    视口

    TODO:待编辑

  • Web API 63 0 1 发布

    示例代码 创建文本节点 var node = domlib.createTextNode("hello,hudaokeji"); 创建元素节点 var node = domlib.createElemnt("div",{ "style" : "width:100%;height:100%" }); 创建节点块 var node = domlib.createFragment("<div><span>label</span><input type='text'/></div>"); 追加节点 //将node作为兄弟节点追加到refNode后面 domlib.appendAfter(node,refNode); //将node作为兄弟节点追加到refNode前面 domlib.appendBefor(node,refNode); //将node作为第一个子节点追加到parentNode下面 domlib.appendChildFirst(node,parentNode); //将node作为最后一个子节点追加到parentNode下面 domlib.appendChild(node,parentNode); 清空和删除节点 //清空node的内容 domlib.empty(node); //移除node domlib.remove(node); 工具函数列表

    uDOMlib所提供的工具函数之中,有一部分与增删节点相关,下面列出部分函数的源代码实现以供参考。

    clone clone: function(node, deep) { var self = this, clone, doc; // TODO: Add feature detection here in the future if (!isIE || node.nodeType !== 1 || deep) { return node.cloneNode(deep); } doc = self.doc; // Make a HTML5 safe shallow copy if (!deep) { clone = doc.createElement(node.nodeName); // Copy attribs each(self.getAttribs(node), function(attr) { self.setAttrib(clone, attr.nodeName, self.getAttrib(node, attr.nodeName)); }); return clone; } return clone.firstChild;

    }

    createElemnt createElement : function(tag,props){ var node = document.createElement(tag); if (props) { utils.mixin(node,props); } return node; } createFragment createFragment: function(html) { var frag = document.createDocumentFragment(), node; if (html) { fragmentContainer.innerHTML = html; } while ((node = fragmentContainer.firstChild)) { frag.appendChild(node); } return frag; } createTextNode createTextNode : function(text){ return document.createTextNode(text); } empty empty : function(node){ while (node.hasChildNodes()) { var child = node.firstChild; node.removeChild(child); } return this; } isChildOf isChildOf: function(node, parent) { while (node) { if (parent === node) { return true; } node = node.parentNode; } return false; } placeAfter placeAfter: function(node,refNode){ var parent = refNode.parentNode; if(parent){ if(parent.lastChild == refNode){ parent.appendChild(node); }else{ parent.insertBefore(node, refNode.nextSibling); } } return this; } placeBefore placeBefore: function(node,refNode){ var parent = refNode.parentNode; if(parent){ parent.insertBefore(node, refNode); } return this; } placeChildFirst placeChildFirst: function(node,parentNode){ if(parentNode.firstChild){ insertBefore(node, refNode.firstChild); } else { parentNode.appendChild(node); } return this; } placeChild placeChild: function(node,parentNode){ parentNode.appendChild(node); return this; } remove remove: function(node){ if(node && node.parentNode){ node.parentNode.removeChild(node); } return this; } replace replace: function(node, oldNode) { oldNode.parentNode.replaceChild(node, oldNode); return this; }
  • Web API 55 0 1 发布

    元素节点的查找 通过节点属性查找

    通过节点的相关属性可以直接取得对象节点的父子兄弟节点。

    属性说明childNodes获取当前元素节点的所有子节点firstChild获取当前元素节点的第一个子节点lastChild获取当前元素节点的最后一个子节点ownerDocument获取该节点的文档根节点,相当与documentparentNode获取当前节点的父节点previousSibling获取当前节点的前一个同级节点nextSibling获取当前节点的后一个同级节点

    通过以上属性取得的子节点和兄弟节点,不仅有元素节点,也有文本节点等其他类型的节点,根据需要可以通过node.nodeType属性进行判断。

    通过ID查找

    节点的ID在DOM文档中具有唯一性,如果知道查找对象节点的ID,这种方法将是查询性能最高的方法。 domlib的find()方法可以通过ID查询节点,下面的代码将会返回contextNode节点(可以是document)的子孙节点中ID为“id1”的节点。

    var node = domlib.find(contextNode,"#id1");

    find()方法内部调用DOM API的contextNode.getElementById()方法。

    通过类名查找

    domlib的find()方法也可以通过类名查询节点,下面的代码将会返回contextNode节点(可以是document)的子孙节点中类名为”cls1”的节点。

    var node = domlib.find(contextNode,".cls");

    find()方法内部调用DOM API的contextNode.getElementsByClassName()方法。

    通过选择符查找

    domlib的find()方法也可以通过指定更复杂的选择符来查询节点,选择符的语法遵从CSS3规范。 下面的代码将会返回contextNode节点(可以是document)的container节点(类名位container的DIV元素)的<a>子元素。

    var node = domlib.find(contextNode,"div.container > a");

    find()方法内部调用DOM API的contextNode.querySelectorAll()或contextNode.querySelector()方法。

    工具函数列表

    uDOMlib所提供的工具函数之中,有一部分与查找元素相关,下面列出部分函数的源代码实现以供参考。

    children children: function(node,selector) { var childNodes = node.childNodes, result = []; for (var i=0;i<childNodes.length;i++){ if (this.matchs(childNodes[i],selector)) { result.push(childNodes[i]); } } return result; } closest closest: function(node,selector,checkSelf) { node = checkSelf ? node : node.parentNode; while (node && !(this.matches(node, selector))){ node = node.parentNode; } return node; } find

    查找元素列表

    find: function(node,selector,single) { var matched,ret; if (matched = selector.match(simpleIdSelectorRE)) { // ID return node.getElementById(matched[1]); } if (matched = selector.match(simpleClassSelectorRE)) { // Class var ret = node.getElementsByClassName(matched[1]); if (single && ret){ ret = ret[0]; } return ret; } // Selector if (single) { return node.querySelector(selector) } else { return node.querySelectorAll(selector) } } findSingle matches matches: function(node,selector) { if (!selector || !node || node.nodeType !== 1) { return false } var matchesSelector = node.webkitMatchesSelector || node.mozMatchesSelector || node.oMatchesSelector || node.matchesSelector; return matchesSelector.call(node, selector) } parents parents: function(node,selector) { var ancestors = []; while (node = node.parentNode) { if (this.matches(node, selector)){ ancestors.push(node); } } return ancestors; }
  • Web API 51 0 1 发布

    获取元素的大小

    Element接口提供了众多属性用于获取元素的各种大小值(单位像素),这些属性通常为只读,并且只有元素已经在DOM树中且CSS属性的display不为none时才有效。

    元素的实际大小

    元素的实际大小就是元素在页面中实际所占控件的大小,包括边框,滚动条,但不包括外边距。

    Element.offsetHeight  元素的高度。Element.offsettWidth  元素的宽度。

    另外,通过调用Element.getBoundingClientRect()方法也可以获得元素的实际大小,该方法同时还返回元素其相对于视口的位置。

    元素客户区的大小

    元素的客户区的大小就是指元素内容及其内边距所占空间的大小,包含内边距,但不包括水平滚动条、边框和外边距

    Element.clientHeight  元素的客户区高度。Element.clientWidth  元素的客户区宽度。 元素滚动区域的大小

    如果元素的CSS属性overflow没有被设置成none,元素的内容多至显示不下时将会被滚动显示。 使用scrollWidth和scrollHeight属性可以获取元素的滚动区域即整个内容的大小。

    Element.scrollHeight  元素的滚动区域高度。Element.scrollWidth 元素的滚动区域宽度。

    另外scrollLeft和scrollTop属性可以用来获取和设定的元素的滚动位置。

    页面和视口 页面的大小

    页面的大小指的是整个页面文档的大小,标准方法是利用document.documentElement(HTML元素)的scrollWidth和scrollHeight属性。

    document.documentElement.scrollWidth  整个文档的宽度document.documentElement.scrollHeight  整个文档的高度 视口的大小

    视口指浏览器窗口中看到的那部分网页面积,标准方法是利用document.documentElement(HTML元素)的clientWidth和clientHeight属性。 这两个属性的返回值不包括整个文档的滚动条,也不包括<html>元素的边框和外边距,但包括<html>元素的内边距。

    document.documentElement.clientWidth  视口的宽度document.documentElement.clientHeight  视口的高度

    其他还有以下方法,不过获取的值可能与标准方法获取的值的范围有所差别。

    document.body.clientHeight/document.body.clientWidth  不包括整个文档的滚动条,也不包括<html>元素的边框,也不包括<body>的边框和滚动条。document.body.offsetHeight/document.body.offsetWidth  不包括整个文档的滚动条,也不包括<html>元素的边框,包括<body>的边框和滚动条。window.innerHeight/window.innerWidth 包括整个文档的滚动条及<html>元素的边框。

    工具函数列表

    uDOMlib所提供的工具函数之中,有一部分与元素大小相关,下面列出部分函数的源代码实现以供参考。

    boundingRect boundingRect : function(node,coords) { if (coords === undefined) { return node.getBoundingClientRect() } else { this.boundingPosition(node,coords); this.size(node,coords); return this; } } clientSize clientSize : function(node) { return { width: node.clientWidth, height: node.clientHeight }; } contentRect contentRect : function(node) { var cs = this.clientSize(node), pex = this.paddingExtents(node); return { left: pex.left, top: pex.top, width: cs.width - pex.left - pex.right, height: cs.height - pex.top - pex.bottom }; } height height : function(node,value) { if (value == undefined) { return this.size(node).height; } else { return this.size(node,{ height : value }); } } pageRect pageRect : function(node,coords) { if (coords === undefined) { var obj = node.getBoundingClientRect() return { left: obj.left + window.pageXOffset, top: obj.top + window.pageYOffset, width: Math.round(obj.width), height: Math.round(obj.height) } } else { this.pagePosition(node,coords); this.size(node,coords); return this; } } rect rect : function(node,coords) { if (coords === undefined) { var // Get *real* offsetParent offsetParent = this.offsetParent(node), // Get correct offsets offset = this.boundingRect(node), parentOffset = this.boundingPosition(offsetParent), mex = this.marginExtents(node), pbex = this.borderExtents(offsetParent); // Subtract parent offsets and element margins return { top: offset.top - pbex.top - mex.top, left: offset.left - pbex.left - mex.left, width: offset.width, height: offset.height } } else { this.position(node,coords); this.size(node,coords); return this; } } size size : function(node,dimension) { if (value == undefined) { return { width : node.offsetWidth, height : node.offsetHeight } } else { var isBorderBox = this.css(node, "boxSizing") === "border-box", props = Object.clone(dimension); if (!isBorderBox) { var pex = this.paddingExtents(node), bex = this.borderExtents(node); if (props.width !== undefined) { props.width = props.width-pex.left-pex.right-bex.left-bex.right; } if (props.height !== undefined) { props.height = props.height-pex.top-pex.bottom-bex.top-bex.bottom; } } styler.css(props); return this; } } width width : function(node,value) { if (value == undefined) { return this.size(node).width; } else { return this.size(node,{ width : value }); } }
  • Web API 61 0 1 发布

    示例代码 获取元素的样式 var backgroundColor = domlib.css(node,"backgroundColor"); 设置元素的样式 domlib.css(node,"backgroundColor","red"); 工具函数列表

    uDOMlib所提供的工具函数之中,有一部分与元素样式相关,下面列出部分函数的源代码实现以供参考。

    addClass

    給元素添加一个或多个类。 该方法不会移除已存在的class属性,仅仅添加一个或多个class属性,添加多个类需使用空格分隔类名。

    addClass: function(el,name){ var re = classRE(name); if (!el.className.match(re)){ el.className += (el.className ? " " : "") + name; } } css

    获取或设置元素的一个或多个样式属性

    css: function(el,property, value){ if (arguments.length < 3) { var computedStyle, computedStyle = getComputedStyle(el, '') if (utils.isString(property)) { return el.style[utils.camelize(property)] || computedStyle.getPropertyValue(property) } else if (utils.isArray(property)) { var props = {}; Array.forEach(property, function(prop){ props[prop] = (el.style[String.camelize(prop)] || computedStyle.getPropertyValue(prop)) }); return props } } var css = '' ; if (type(property) == 'string') { if (!value && value !== 0) el.style.removeProperty(dasherize(property)); else css = dasherize(property) + ":" + maybeAddPx(property, value) } else { for (key in property) if (!property[key] && property[key] !== 0) el.style.removeProperty(dasherize(key)); else css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';' } el.style.cssText += ';' + css; return this; } hasClass

    检查元素是否包含指定的类。

    hasClass: function(el,name){ var re = classRE(name); return el.className.match(re); } removeClass

    从元素移除一个或多个类

    removeClass: function(el,name){ var re = classRE(name); if (el.className.match(re)){ el.className = el.className.replace(re, " "); } return this; } toggleClass

    对元素的一个或多个类进行切换。 该方法检查元素是否已设置指定的类。如果不存在则添加类,如果已设置则删除之。

    toggleClass: function(el,name){ var re = classRE(name); if (el.className.match(re)){ el.className = el.className.replace(re, " "); } else { el.className += (el.className ? " " : "") + name; } return this; }
  • Web API 72 0 1 发布

    获取和设置HTML属性文本 var disabled = nodelib.attr(node,"disabled"); nodelib.attr(node,"disabled",""); 获取和设置DOM对象属性 var disabled = nodelib.prop(node,"disabled"); nodelib.prop(node,"disabled",false); 工具函数列表

    uDOMlib所提供的工具函数之中,有一部分与元素属性相关,下面列出部分函数的源代码实现以供参考。

    attr

    获取或设置元素的attribute(HTML标签属性)值。

    attr: function(node,name, value) { if (value === undefined){ if (typeof name === "object"){ for (var attr in name){ this.attr(node,attr,name[atrr]); } return this; } else { return node[name]; } } else { node[name] = value; return this; } } data

    获取或设置元素给定名称的数据存储的值。

    data: function(node,name, value) { var attrName = 'data-' + name.replace(capitalRE, "-$1").toLowerCase() if (value === undefined){ var data = this.attr(node,attrName,value); return data !== null ? deserializeValue(data) : undefined; } else { return this.attr(node,attrName,value); } } html

    获取或设置元素的Html内容。 html()内部使用DOM节点的innerHTML属性,适用于任意HTML元素。

    html: function(node,html) { if (html === undefined){ return node.innerHTML; } else { this.empty(node); node.innerHTML = html; //TODO:will be checkd return this; } } prop

    获取或设置元素的property(特性)值。 prop()方法返回的是节点作为一个JavaScript对象所拥有的特性(property)值。 与attr()方法不同,prop()返回的值具有其本来的数据类型,如针对<input type=“checkbox”/>元素调用prop(“checked”),其返回值将是Boolean型的true或false。

    prop: function(node,name, value) { name = propMap[name] || name; if (value === undefined){ return node[name]; } else { node[name] = value; return this; } } removeAttr removeAttr: function(node,name) { name.split(' ').forEach(function(attr) { setAttribute(node, attr); }); return this; } text

    获取或设置元素的文本内容。 .text() 方法不能使用在input元素或scripts元素上。 input 或 textarea 需要使用 .val() 方法获取或设置文本值。得到scripts元素的值,使用.html()方法

    text: function(node,text) { if (text === undefined){ return node.textContent; } else { node.textContent = text == null ? '' : '' + text return this; } } val

    获取或设置元素的当前值。 val()方法主要适用于表单元素,如input, select 和 textarea。 如果select元素设置了multiple属性,.val()返回一个包含每个选择项值的数组

    val: function(node,value) { if (value === undefined){ if (node.multiple) { // select multiple values var selectedOptions = this.find(node,"option").filter(function(){ return this.selected }); return this.pluck(selectedOptions,"value"); } else { return node.value; } } else { node.value = value; return this; } }
  • Web API 59 0 1 发布

    用canvas画一个9*9的表格

    (function(global) { 'use strict'; function _extend(obj1, obj2) { for (var i in obj2) { if (obj2.hasOwnProperty(i)) { obj1[i] = obj2[i]; } } } function GridFunny(options) { this.grid = {}; this.gridOfX = {}; this.gridOfY = {}; this.settings = { container: document.body, gridColor: "#ccc", // 格子的颜色 gridNum: 9, // 格子的数量 canvasSize: { width: 500, height: 500 }, // canvas的尺寸 generateGridKey: function(x, y) { return [x, y].join("-"); }, // 创建每个格子在grid对象中的key onDraw: function() { }, // 提供绘画钩子方法,方便定制绘画 fillGrid: function(keyX, keyY, pixelX, pixelY) { }, // 填充每个格子内容的方法 contextType: "2d", // canvas文本类型(2d或者3d) border: 1 // 表格的边框大小 }; _extend(this.settings, options || {}); return this; } GridFunny.prototype.start = function() { this.canvas = this._initCanvas(); this.context = this.canvas.getContext(this.settings.contextType); this._drawBoard(); } GridFunny.prototype._initCanvas = function() { var canvas = document.createElement("canvas"); canvas.width = this.settings.canvasSize.width; canvas.height = this.settings.canvasSize.height; this.settings.container.appendChild(canvas); return canvas; } GridFunny.prototype._drawBoard = function() { var width = this.settings.canvasSize.width, height = this.settings.canvasSize.height, num = this.settings.gridNum, border = this.settings.border, halfBorder = border / 2, context = this.context, color = this.settings.gridColor, pixelX = (width - border) / (num + 2), pixelY = (height - border) / (num + 2), rectXSize = pixelX * (num + 1), rectYSize = pixelY * (num + 1); context.clearRect(0, 0, width, height); context.beginPath(); /* 垂直线 */ for (var i = 0, x = pixelX; x <= rectXSize; x += pixelX) { i++; var beginCoordinate = halfBorder + x; if (i <= num) this.gridOfX[i] = beginCoordinate; context.moveTo(beginCoordinate, pixelX); context.lineTo(beginCoordinate, rectXSize); } /* 水平线 */ for (var j = 0, y = pixelY; y <= rectYSize; y += pixelY) { j++; var endCoordinate = halfBorder + y; if (j <= num) this.gridOfY[j] = endCoordinate; context.moveTo(pixelY, endCoordinate); context.lineTo(rectYSize, endCoordinate); } this._initGridCoordinate(pixelX, pixelY); context.closePath(); this.settings.onDraw.call(this); /* 开始画 */ context.strokeStyle = color; context.stroke(); } GridFunny.prototype._initGridCoordinate = function(pixelX, pixelY) { var context = this.context, grid = this.grid, gridOfX = this.gridOfX, gridOfY = this.gridOfY; for (var keyX in gridOfX) { for (var keyY in gridOfY) { // 记录每个格子的坐标 var key = this.settings.generateGridKey(keyX, keyY); grid[key] = [gridOfX[keyX], gridOfY[keyY]]; this.settings.fillGrid.call(this, keyX, keyY, pixelX, pixelY); } } } // Export Pig into the global scope. if (typeof define === 'function' && define.amd) { define(function() {return GridFunny;}); } else if (typeof module !== 'undefined' && module.exports) { module.exports = GridFunny; } else { global.GridFunny = GridFunny; } }(this)); var grid = new GridFunny({ gridColor: "green" }); grid.start();

    主要用到的方法:

    clearRect(x, y, width, height):清空所选矩形块beginPath:开始绘制路径moveTo(x, y):将画笔移到坐标为(x, y)的地方lineTo(x, y):画一条到坐标(x, y)为止的线closePath:结束绘制路径strokeStyle:给画笔添加颜色(通俗的说法是给画笔加所给颜色的墨水),示例中默认是灰色#cccstroke:根据绘制的路径以及定义的颜色,绘制图画

    以上是代码的执行效果。

  • Web API 61 0 1 发布

    概述

    Canvas API中提供处理形状的简单方法有:

    fillRect:它的四个参数分别为矩形左上角顶点的x坐标、y坐标,以及矩形的宽和高,在绘制矩形前可以使用fillStyle属性设置矩形的填充色 CanvasRenderingContext2D.fillRect(x, y, w, h); strokeRect:以fillRect类似,绘制空心矩形 CanvasRenderingContext2D.strokeRect(x, y, w, h); clearRect:清除给定坐标的矩形区域 CanvasRenderingContext2D.clearRect (x, y, w, h);

    上面的方法只能处理简单的矩形,当需要处理其他复杂形状时可以使用paths,处理流程:

    1. 使用beginPath方法开始一个新的路径绘制

    2. 使用下面的方法绘制图形:

    moveTo:设置线段的起点(x, y) CanvasRenderingContext2D.moveTo(x, y); lineTo:设置线段的终点(x, y) CanvasRenderingContext2D.lineTo(x, y); rect:绘制矩形,与fillRect和strokeRect方法不同的是,使用rect方法必须配合使用stroke或者fill方法着色 CanvasRenderingContext2D.rect(x, y, w, h); quadraticCurveTo:绘制二次贝塞尔曲线 CanvasRenderingContext2D.quadraticCurveTo(cpx, cpy, x, y); bezierCurveTo:绘制三次方贝塞尔曲线 CanvasRenderingContext2D.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); arc:绘制弧或者曲线 CanvasRenderingContext2D.arc(x, y, r, start, end, anticlockwise); arcTo:绘制两切线之间的弧或曲线 CanvasRenderingContext2D.arcTo(x1, y1, x2, y2, radius);

    3. 使用closePath结束路径绘制 4. 使用stroke或者fill方法给绘制好的路径着色,在这之前使用strokeStyle属性设置填充色,还可以赋值lineWidth设置线条的大小

    代码示例

    abstract一节中,我们绘制了一个9*9的空表格,现在我们来为每个表格填充数字以及x与y轴坐标的乘积:

    // GridFunny定义与[[36:26:canvas:abstract]]一节中一致 // 添加一个获取随机颜色的方法 GridFunny.prototype._randColor = function() { var colors = [ "#cfd9df", "#a1c4fd", "#8fd3f4", "#e6dee9", "#c3cfe2", "#a8edea", "#e0c3fc", "#ebbba7", "#fff1eb", "#accbee", "#c1dfc4", "#deecdd", "#fbfcdb", "#6a85b6", "#9face6" ]; return colors[Math.floor(Math.random() * colors.length)]; } var grid = new GridFunny({ gridColor: "green", fillGrid: function(keyX, keyY, pixelX, pixelY) { this.context.fillStyle = this._randColor(); this.context.fillRect(this.gridOfX[keyX], this.gridOfY[keyY], pixelX, pixelY); } }); grid.start();

    abstract一节中,我们其实使用了path的相关方法绘制了一个基本的9*9表格,处理流程是:

    1. 使用clearRect(0, 0, width, height)方法清空矩形区域 2. 调用beginPath,开始路径绘制 3. 按照单元表格的大小分别在x轴与y轴绘制实线,步骤是首先使用moveTo设置线段起点坐标,然后调用lineT设置线段的终点坐标 4. 使用closePath方法结束路径的绘制,赋值strokeStyle设置填充色,最后调用stroke方法着色。

    本节示例代码中,在基础表格之上,通过调用fillRect以及赋值fillStyle属性为单元表格填充随机的颜色。

    代码的执行效果如下:

  • Web API 64 0 1 发布

    概述

    drawImage方法将所给图片绘制到canvas。

    使用方法 CanvasRenderingContext2D .drawImage(image, dx, dy); CanvasRenderingContext2D .drawImage(image, dx, dy, dw, dh); CanvasRenderingContext2D .drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh); 参数说明 image:图形数据,可以是图像数据也可以是img标签。sx:从图形x轴坐标x处截取sy:从图形y轴坐标y处截取sw: 截取图形的宽sh:截取图形的高dx:从目标canvas的x轴x处绘制dy:从目标canvas的y轴y处绘制dw: 绘制的宽dh:绘制的高 代码示例

    todataurl一节中我们为GridFunny添加了一个toDataURL的方法,将canvas直接转换为图形数据, 本节中的示例,使用这个被转换的数据,并将其重新绘制到另一个canvas中:

    // 为GridFunny添加一个clone方法 GridFunny.prototype.clone = function(options, callback) { if (!this._started) this.start(); var self = this, width = 300, height = 300, destGridW = this._canvasRatio("width", options.width || width) * this.pixelX, destGridH = this._canvasRatio("height", options.height || height) * this.pixelY, _opts = this._extendObject({ type: "image/png", opts: {}, width: width, height: height, sx: this.pixelX, sy: this.pixelY, sw: options.gridNum ? options.gridNum * this.pixelX : this.settings.canvasSize.width - this.pixelX * 2, sh: options.gridNum ? options.gridNum * this.pixelY : this.settings.canvasSize.height - this.pixelY * 2, dx: destGridW, dy: destGridH, dw: (options.width || width) - (destGridW * 2), dh: (options.width || width) - (destGridH * 2) }, options || {}); this.toDataURL(_opts.type, _opts.opts, function(canvas, data) { var image = new Image(); image.src = data; image.onload = function() { var _canvas = self._initCanvas(_opts.width, _opts.height), ctx = _canvas.getContext('2d'); ctx.drawImage(image, _opts.sx, _opts.sy, _opts.sw, _opts.sh, _opts.dx, _opts.dy, _opts.dw, _opts.dh) callback(_canvas); }; }); } // 调用 // 剪切三个格子 grid.clone({ gridNum: 3, width: 300, height: 300 }, function(canvas) { grid.settings.container.appendChild(canvas); }); // 全部复制 grid.clone({ width: 300, height: 300 }, function(canvas) { grid.settings.container.appendChild(canvas); });

    clone参数:

    gridNum:剪切的格子数,没有则为全部width:复制后canvas的宽height:复制和canvas的高(s|d)(x,y,w,h):默认不传,则根据gridNum自动计算,有传值则根据所传值处理图片

    代码的执行效果如下:

  • Web API 48 0 1 发布

    概述

    Canvas API中提供了两种绘制文本的方法:

    fillText:绘制文本 CanvasRenderingContext2D.fillText(text, x, y); CanvasRenderingContext2D.fillText(text, x, y, maxWidth); strokeText:添加空心字 CanvasRenderingContext2D.strokeText(text, x, y); CanvasRenderingContext2D.strokeText(text, x, y, maxWidth);

    注意:fillText方法不支持文本断行,即所有文本出现在一行内。所以,如果要生成多行文本,只有调用多次fillText方法。 绘制文本的时候还可以为文本添加其他属性:

    font:设置文本的样式textAlign:设置文本水平对齐,'start','end','left','right','center'textBaseline:设置文本垂直对齐,'top','hanging','middle','alphabetic','ideographic','bottom' 示例代码

    abstract一节中,我们绘制了一个9*9的空表格,现在我们来为每个表格填充数字以及x与y轴坐标的乘积:

    // GridFunny定义与[[36:26:canvas:abstract]]一节中一致 var grid = new GridFunny({ gridColor: "green", fillGrid: function(keyX, keyY, pixelX, pixelY) { var paddingX = pixelX / 4, paddingY = pixelY / 4; if (keyX <= keyY) { this.context.fillStyle = "black"; } else { this.context.fillStyle = "blue"; } this.context.font = "20px Arial"; this.context.fillText(keyX * keyY, this.gridOfX[keyX] + paddingX * 1.5, this.gridOfY[keyY] + paddingY * 2.5); } }); grid.start();

    示例代码中使用了GridFunny提供的每个格子的坐标,然后调用fillText方法将坐标的乘积绘制到每个单元表格中。

    这里有一个问题,由于记录单元表格的坐标是左上角的,所以在绘制文本的时候,位置并不是我们想要看到的居中,而是会出现在单元表格左上角的外面,如下图所示: 为了解决这个问题我们在绘制文本的时候做了下位置偏移(临时解决方案,这不是好的实现方法,应该考虑一个更为通用的方法)

    代码的执行效果如下:

  • Web API 52 0 1 发布

    概述

    Canvas API中提供了一系列与阴影相关的属性来设置阴影。

    shadowOffsetX:设置水平方向的阴影,默认值是0 CanvasRenderingContext2D.shadowOffsetX shadowOffsetY:设置垂直方向的阴影,默认值是0 CanvasRenderingContext2D.shadowOffsetY shadowBlur:设置阴影的模糊度,默认值是0 CanvasRenderingContext2D. shadowBlur shadowColor:设置阴影的颜色,默认为黑色 CanvasRenderingContext2D. shadowColor 代码示例

    GridFunny定义与Canvas概述一节中一致

    var grid = new GridFunny({ nextDraw: function() { var num = this.settings.gridNum, canvasSize = this.settings.canvasSize, cX = canvasSize.width / 2, cY = canvasSize.height / 2, gradient = this.context.createRadialGradient(cX - this.pixelX, cY - this.pixelY, 20, cX, cY, 110); gradient.addColorStop(0, 'yellow'); gradient.addColorStop(1, 'green'); this.context.fillStyle = gradient; this.context.shadowBlur = 6; this.context.shadowOffsetX = 10; this.context.shadowOffsetY = 10; this.context.shadowColor = "#ccc"; this.context.beginPath(); this.context.arc(cX, cY, 110, 0, 2 * Math.PI, false); this.context.fill(); this.context.closePath(); } }); grid.start();

    代码的执行效果如下:

  • Web API 52 0 1 发布

    概述

    Canvas API中提供设置渐变色的方法有:

    createLinearGradient:线性渐变createRadialGradient:径向渐变 代码示例 线性渐变 CanvasRenderingContext2D.createLinearGradient(x0, y0, x1, y1); CanvasGradient.addColorStop(position, color); x0:渐变开始点x坐标y0:渐变开始点y坐标x1:渐变结束点x坐标y1:渐变结束点y坐标position:设定的颜色离渐变结束点的偏移量(0~1)color:绘制时使用的颜色

    GridFunny定义与abstract一节中一致

    // GridFunny定义 var grid = new GridFunny({ onDraw: function() { var num = this.settings.gridNum, gradient = this.context.createLinearGradient(0, 0, 0, this.pixelY * num); gradient.addColorStop(0, 'red'); gradient.addColorStop(0.5, 'green'); gradient.addColorStop(1, 'blue'); this.context.fillStyle = gradient; this.context.fillRect(this.gridOfX[1], this.gridOfY[1], this.pixelX * num, this.pixelY * num); } }); grid.start();

    以下是代码的执行效果:

    径向渐变(发散) CanvasRenderingContext2D.createRadialGradient(x0, y0, r0, x1, y1, r1) CanvasGradient.addColorStop(position, color); x0:发散开始圆心x坐标y0:发散开始圆心y坐标r0:发散开始圆的半径x1:发散结束圆心的x坐标y1:发散结束圆心的y坐标r1:发散结束圆的半径position:设定的颜色离渐变结束点的偏移量(0~1)color:绘制时使用的颜色

    GridFunny定义与abstract一节中一致

    // GridFunny定义 var grid = new GridFunny({ nextDraw: function() { var num = this.settings.gridNum, canvasSize = this.settings.canvasSize, cX = canvasSize.width / 2, cY = canvasSize.height / 2, gradient = this.context.createRadialGradient(cX,cY, 20, cX, cY, 110); gradient.addColorStop(0, 'yellow'); gradient.addColorStop(1, 'green'); this.context.fillStyle = gradient; this.context.beginPath(); this.context.arc(cX, cY, 110, 0, 2 * Math.PI, false); this.context.fill(); this.context.closePath(); } }); grid.start();

    以下是代码的执行效果:

  • Web API 50 0 1 发布

    概述

    Canvas API中提供的变形方法主要有:

    scale:缩放 CanvasRenderingContext2D.scale(x, y) rotate:旋转 CanvasRenderingContext2D.rotate(angle) translate:重新映射画布上的 (0,0) 位置 CanvasRenderingContext2D.translate(x, y) transform:转换矩阵 CanvasRenderingContext2D.transform(a, b, c, d, e, f) setTrasform:将当前转换重置为单位矩阵。然后运行 transform() CanvasRenderingContext2D.setTransform(a, b, c, d, e, f) 代码示例

    绘制图片一节示例中我们使用GridFunny提供的clone方法实现类似缩放的效果,下面使用scale方法再次实现缩放:

    // 分别为GridFunny添加scale、rotate、translate、transform方法 var grid = new GridFunny({ gridColor: "green", canvasClassName: "transform-canvas", nextDraw: function() { var context = this.context, x = this.pixelX + 50, y = this.pixelY + 10, w = 240, h = 50; context.fillStyle = '#ccc'; context.strokeStyle = 'red'; context.font = '30px Arial'; context.fillRect(x, y, w, h); context.strokeText("transform canvas", x + 5, 85); } }); grid.start(); // scale grid.scale({ width: 300, height: 300 }, function(canvas) { canvas.className = grid.settings.canvasClassName; grid.settings.container.appendChild(canvas); }); // rotate grid.rotate({ angle: 30 * Math.PI / 180 }, function(canvas) { canvas.className = grid.settings.canvasClassName; grid.settings.container.appendChild(canvas); }); // translate grid.translate({ x: 120, y: 50 }, function(canvas) { canvas.className = grid.settings.canvasClassName; grid.settings.container.appendChild(canvas); }); // transform grid.transform({ a: 0.5, b: 0.4, c: -0.2, d: 1.2, e: 200, f: 0 }, function(canvas) { canvas.className = grid.settings.canvasClassName; grid.settings.container.appendChild(canvas); });

    rotate、translate、transform方法会对canvas进行不同程度的选择,如果是原始尺寸操作的话,有部分不能完全显示,这时需要配合scale对原始canvas进行缩放,以便显示全图。

    代码的执行效果如下:

  • Web API 56 0 1 发布

    概述

    配合使用JavaScript中提供的requestAnimationFrame方法,可以很容易的在canvas中实现动画效果

    一般来说,需要按照下面的步骤来创建动画:

    1. 清空canvas:使用clearRect方法,清空区域。 2. 保存canvas状态:如果你要改变一些会改变canvas状态的设置(样式,变形之类的),又要在每画一帧之时都是原始状态的话,你需要先保存一下。 3. 绘制动画图形(animated shapes) 4. 恢复canvas状态 代码示例

    GridFunny定义与Canvas概述一节中一致

    window.requestAnimFrame = (function() { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function( /* function */ callback, /* DOMElement */ element) { window.setTimeout(callback, 1000 / 60); }; })(); var grid = new GridFunny({ nextDraw: function() { var time = new Date().getTime() * 0.002, num = this.settings.gridNum, canvasSize = this.settings.canvasSize, cX = canvasSize.width / 2, cY = canvasSize.height / 2, x = Math.sin(time) * this.pixelX + cX, y = Math.cos(time * 0.9) * this.pixelY + cY, gradient = this.context.createRadialGradient(x, y, 20, cX, cY, 110); gradient.addColorStop(0, 'yellow'); gradient.addColorStop(1, 'green'); this.context.fillStyle = gradient; this.context.beginPath(); this.context.arc(cX, cY, 110, 0, 2 * Math.PI, false); this.context.fill(); this.context.closePath(); } }); grid.start(); var animate = function() { requestAnimationFrame(animate); grid._drawBoard(); }; animate();

    代码的执行效果如下:

  • Web API 55 0 1 发布

    简介

    可缩放矢量图形(英语:Scalable Vector Graphics,SVG)是一种基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式。SVG由W3C制定,是一个开放标准。

    使用场景

    SVG基于VML,这意味着SVG DOM中的每个元素都是可操作的(为元素添加JavaScript事件),在SVG中,被绘制的图形都可以当成一个可操作的对象,如果该对象的属性发生变化,可以通过事件机制,让浏览器实时反映该属性的变化即重绘图形。SVG提供了一系列的图形元素、动画以及事件机制,适用于静态图片的展示,比如google地图。

    目前主要的使用场景有:

    Logo图矢量图UI组件信息化图标图标(字体图标、loading图标等) 实例

    画一个正方形:

    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <rect x="10" y="10" height="100" width="100" style="stroke:#ff0000; fill: #0000ff"/> </svg>

    效果图:

    API 矩形:rect <rect x="10" y="10" fill="#eee" width="100" height="100"/> 圆:circle <circle cx="10" cy="10" r="10" fill="red"/> 椭圆:ellipse <ellipse cx="50" cy="60" fill="#eee" rx="20" ry="30"/> 直线:line <line x1="10" y1="10" x2="20" y2="20" fill="#eee" stroke-width="2" stroke="black"/> 折线:polyline <polyline stroke="black" fill="#eee" points="10, 80 40, 50 30, 60 100, 10"/> 多边形:polygon <polygon fill="#eee" points="60,20 100,40 100,80 60,100 20,80 20,40"/> 路径:path <path fill="#eee" d="M37,17v15H14V17H37z M50,0H0v50h50V0z"/> 动画:animate <animate id="animate" attributeType="XML" attributeName="d" from="-100" to="120" dur="0.3s" repeatCount="indefinite" fill="freeze" values="...."/>
  • Web API 38 0 1 发布

    WebGL(Web Graphics Library)是HTML5规范中的一部分,可以用来渲染三维场景。

    WebGL源自OpenGL ES(OpenGL for Embedded Systems 是OpenGL三维图形API的子集)。

    示例代码// 创建canvas function createCanvas(width, height) { var canvas = document.createElement("canvas"); canvas.width = width || 300; canvas.height = height || 300; return canvas; } // 创建着色器 function createShader(webGL, source, type) { var shader = webGL.createShader(type); webGL.shaderSource(shader, source); webGL.compileShader(shader); return shader; } // 初始化webGL function initWebGL(canvas) { var webGL = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); if (!webGL) { console.log("当前浏览器不支持WebGL,请切换到支持WebGL的浏览器,比如Chrome"); return null; } else { return webGL; } } // 创建矩形 function drawRect(webGL, program) { var buffer = webGL.createBuffer(); webGL.bindBuffer(webGL.ARRAY_BUFFER, buffer); webGL.bufferData( webGL.ARRAY_BUFFER, new Float32Array([-1.0, -1.0,1.0, -1.0, -1.0, 1.0, -1.0, 1.0,1.0, -1.0,1.0, 1.0]), webGL.STATIC_DRAW ); // vertex data var positionLocation = webGL.getAttribLocation(program, "a_position"); webGL.enableVertexAttribArray(positionLocation); webGL.vertexAttribPointer(positionLocation, 2, webGL.FLOAT, false, 0, 0); } // 入口函数 function init() { var canvas = createCanvas(), VER_SHADER_SRC = "attribute vec4 a_position;\n" + "void main() {\n" + "gl_Position = a_position;\n" + "}", FRAG_SHADER_SRC = "precision mediump float;\n" + "void main() {\n" + "gl_FragColor = vec4(1, 0, 0.5, 1);\n" + "}"; document.body.appendChild(canvas); var webGL = initWebGL(canvas); if (webGL) { webGL.clearColor(0.0, 0.0, 0.0, 1.0); webGL.clear(webGL.COLOR_BUFFER_BIT | webGL.DEPTH_BUFFER_BIT); var vertex = createShader(webGL, VER_SHADER_SRC, webGL.VERTEX_SHADER), frag = createShader(webGL, FRAG_SHADER_SRC, webGL.FRAGMENT_SHADER); var program = webGL.createProgram(); webGL.attachShader(program, vertex); webGL.attachShader(program, frag); webGL.linkProgram(program); webGL.useProgram(program); drawRect(webGL, program); webGL.drawArrays(webGL.TRIANGLES, 0, 6); } }代码说明

    WebGLShader(WebGL着色器),WebGL只关心两件事:位置坐标与颜色,所有WebGL程序都是基于这两个元件来构造的,常用的方法是使用两个着色器来实现:

    顶点着色器(vertex shader):返回位置坐标
    像素着色器(fragment shader):返回颜色

    vec4()构造函数用于生成颜色,示例代码中vec4(1, 0, 0.5, 1)的数字的含义:

    第一个1:代表红色

    0:代表绿色

    0.5: 代表蓝色

    第二个1:代表alpha



    在WebGL中颜色的取值范围是0到1.

    具体方法:

    createShader:生成相应类型的WebGLShader

    shaderSource:生成GLSL的回调函数

    compileShader:编译着色器

    WebGLProgram(WebGL环境)着色器编译完后,需要将着色器链接到WebGLProgram:

    createProgram:创建一个WebGL环境

    attachShader:附加着色器

    linkProgram:将着色器连接到WebGL环境中

    提供数据:

    getAttribLocation:从当前环境中寻找定义的属性,即查找示例中初始化顶点着色器时定义的a_position。

    createBuffer:创建buffer(缓存区)

    bindBuffer:声明变量,并指向上一步创建的buffer

    bufferData:赋值数据到指定变量,比如示例中的ARRAY_BUFFER

    清空canvas:

    clearColor:

    clear:

    使用创建的WebGL环境:将当前的WebGL环境告知GPU程序

    useProgram:

    告知WebGL从buffer中获取数据的方式:

    enableVertexArribArray:激活属性

    vertexAtrribPointer:获取数据

    绘制图形:WebGL执行GLSL程序

    drawArrays:这是WebGL提供的一个渲染函数

    效果

  • Web API 55 0 1 发布

    在过去,想要在网页上构建有声web只能借助Flash等插件,自从web步入HTML5时代后,除插件机制外,我们还可以运用HTML5提供的原生API来实现这一需求。

    本节我们就来探究一下这些原生API。

      概述 简介

    Web Audio API最早是Chrome社区提出并支持的,它是一套全新的相对独立的接口系统,对音频文件拥有很高的处理权限以及内置相关的音频专业效果的处理方法,可以完全独立于<audio>标签存在。简单的说它就是一组JavaScript API,它提供了一系列处理与合成音频的方法。

    Web Audio API本身并不是<audio>标签的替代品,而是对<audio>标签功能上的补充。如果是简单的展现音频则<audio>标签足以应对,如果需要负责的音频操作,则应该是使用Web Audio API。

    特点

    * 更精准的时间控制 * 可独立于<audio>标签,允许多音频文件同时播放 * 模块化的接口设计方式,让音频操作更具灵活特性 * 更多音频专业对口的操作方法

    工作流程

    1. 创建AudioContext实例对象(下文中简称ac) 2. 为ac内置音源,如<audio>标签,震动发声器,音频流等 3. 创建效果节点(effect node)如reverb、biquad filter、compressor等 4. 选择音频的最终输出节点,如电脑扬声器 5. 连接各处理后的效果节点(源-效果-目的地 输入-处理-输出)

    名词简介 AudioContext

    AudioContext是管理和控制音频的核心,作为音频接口上下文对象,它包含了音频信号的路由图,用来连接各AudioNodes。

    AudioNodes

    音频的输入、输出以及中间处理的节点或模块

    AudioDestinationNode

    音频信号处理后的最终目的地

    AudioBuffer

    音频缓冲器,表示驻留在内存中的音频内容

    AudioBufferSourceNode

    由AudioBuffer产生音频的AudioNode

    MediaElementAudioSourceNode

    来源于audio标签、video标签或其他元素的音频资源

    AnalyserNode

    提供实时频率以及时间域分析信息的节点,它是一个AudioNode,将音频流从输入传递到输出,允许获取和处理生成的数据,并创建音频可视化。 * .frequencyBinCount * .getByteFrequencyData

    路由图

    AudioContext中包含了许许多多的几点,大致分为三类:源、目标和中间节点。 一个完整的路由图就是将每个用到的节点以串联的方式一个一个连接起来组成的。这其中源节点和目的节点是必须的而中间节点(提供了各式各样的功能和效果)则是可选的。

    代码示例 基本操作 window.onload = init; var context, bufferLoader; // loading audio file function init () { window.AudioContext = window.AudioContext || window.webkitAudioContext; context = new AudioContext(); bufferLoader = new BufferLoader(context, [ "somPath/someFile.wav", "somePath/anotherFile.wav" ], finishedLoading); bufferLoader.load(); }; // control bufferList function finishedLoading(bufferList) { bufferList.forEach(function(buffer) { playSound(buffer, 0); }); }; // play sound with given buffer and time function playSound(buffer, time) { time = time || 0; var source = context.createBufferSource(); source.buffer = buffer; source.connect(context.destination); source.start(time); }; // change volume sound function changeVolume(source, value) { var gainNode = context.createGain(); source.connect(gainNode); gainNode.connect(context.destination); gainNode.gain.value = value; } 静音 var mute = document.querySelector(".mute"); mute.onclick = function() { if(mute.id === "") { gainNode.disconnect(context.destination); mute.id = "activated"; mute.innerHTML = "Unmute"; } else { gainNode.connect(context.destination); mute.id = ""; mute.innerHTML = "Mute"; } } 使用Canvas实现可视化效果 // 获取实时表示频率信息的数组 var analyser = context.createAnalyser(), array = new Uint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(array); function createCanvas(width, height) { var canvas = document.createElement("canvas"); canvas.width = width || 300; canvas.height = height || 300; return canvas; } var canvas = createCanvas(), cxt = canvas.getContext("2d"); function draw(size) { cxt.clearRect(0, 0, canvas.width, canvas.height); var w = canvas.width / size; for(i = 1; i < size; i++) { var h1 = array[i] / 256 * canvas.height; h2 = canvas.height - h1; cxt.beginPath(); cxt.fillRect(w * i, h2, w * 0.6, h1); cxt.closePath(); } }
  • Web API 43 0 1 发布

    概述

    图像处理API是通过Image对象来提供的。如上图所示,Image是一个封装了HTMLImageElement接口的构造器,和document.createElement('img')一样,返回一个 HTMLImageElement 实例。

    代码示例 图像预加载

    使用Image对象可以实现图像预加载功能。如下所示:

    function loadImage(url, callback) { var img = new Image(); //创建一个Image对象,实现图像的预下载 img.src = url; img.onload = function () { //图像下载完毕时异步调用callback函数。 callback(img); }; }; 获取图像的大小

    在图像加载完毕之后,我们可以在回调函数里获取图像的大小,作相应的处理。

    var imgUrl = "/images/sample1.jpg"; div1 = document.getElementById("div1"); var callback = function(img) { //将图像设为DIV的背景并自动调整DIV的大小。 div1.style.backgroundImage = "url('" + img.src+ "')"; div.style.width = img.width + "px"; div.style.height = img.height + "px"; }; loadImage(imgUrl,callback);
  • Web API 51 0 1 发布

    在HTML5 Web中我们可以很方便的使用原生API来操作视频文件。

      示例 播放视频

    首先来看一下视频的例子

    <video width="640" height="480" poster="video.jpg" controls autoplay preload loop tabindex="0"> <source src="video.webm" type="video/webm"> <source src="video.ogv" type="video/ogg"> <source src="video.mp4" type="video/mp4"> <track src="video.vtt" kind="subtitles" srclang="en" label="English" default> </video>

    <video>标签的属性:

    width:视频的宽度height: 视频的高度poster:视频的替代图片,指定在视频加载完之前显示的图片controls:是否适用原生的视频控制UIpreload:是否预加载视频autoplay:是否自动播放视频loop:是否循环播放tabindex:是否适用键盘控制播放

    <video>标签的嵌套标签:

    <source>:视频文件地址描述标签,指明地址与格式<track>:视频信息描述标签 使用CSS与JavaScript增强视频的展现

    <video>标签和其它HTML元素一样,可以通过为其附加事件,如拖动、鼠标、焦点事件等,来处理相关操作。同时也能使用常规的css规则来定制视频的样式

    比如下面的代码为video附加一个canplay的事件

    video.addEventListener("canplay", function(e) { this.volume = 0.6; this.currentTime = 1; this.play(); }, false);

    视频的属性,方法以及事件: 属性: * currentTime:当前播放的时间 * volume:当前的音量 * muted:返回视频是否应该被静音 * playbackRate: 播放速度 * currentSrc:当前播放视频的地址 * videoWidth & videoHeight:视频的宽和高

    方法:

    load:重新加载视频play:播放pause: 暂停canPlayType:判断所给类型的视频格式是否支持addTextTrack:向视频添加新的文本轨道。

    其他属性参照http://techbrood.com/jsref?p=dom-obj-video 事件:

    canPlaythrough:当浏览器认为可以完全播放当前视频时触发ended:视频结束时触发error:视频播放出错时触发playing:视频播放时触发(刚开始播放或者暂停后再播放)progress:加载视频时触发waiting:一个操作在等另一个操作时触发loadedmetadata:当浏览器加载完元数据时触发

    其他具体事件可参看https://developer.mozilla.org/zh-CN/docs/Web/Guide/Events/Media_events

    与其他标签配合增强功能 canvas

    使用canvas可以很方便的在视频里导出导入图片。比如截屏功能可以这样实现:

    function grabScreenshot() { var canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"); ctx.drawImage(video, 0, 0, videoWidth, videoHeight); var img = new Image(); img.src = canvas.toDataURL("image/png"); img.width = video.width; container.appendChild(img); } SVG

    使用SVG为视频添加蒙层,比如:

    <svg id='image' version="1.1" xmlns="http://www.w3.org/2000/svg"> <defs> <filter id="myblur"> <feGaussianBlur stdDeviation="1" /> </filter> </defs> </svg> <style> video { filter:url(#myblur); border: 2px solid red; } </style>
  • Web API 46 0 1 发布

    概述

    Cookie API是通过document.cookie属性来实现的。cookie是存储在访问者的计算机中的变量,与页面相关联。

    cookie包含在HTTP协议中,服务器端程序可以为页面创建或更新cookie值,通过HTTP请求回送给客户端,浏览器则会将cookie值自动保存起来, 再次请求该页面时,浏览器会自动把与该页面相关联的所有cookie值放到HTTP请求中一起发送给服务器。

    因为cookie能被自动处理这个特点,服务器端WEB应用程序的Session ID通常就是放在cookie里进行保存的。

    格式  每个cookie的格式:<cookie名>=<值>;名称和值都必须是合法的标志符。大小限制  cookie是有大小限制的,每个cookie所存放的数据不可超过4kb,如果cookie字符串的长度超过了4kb,则该属性将返回空字符串。有效期限  cookie是存在有效期的。在一般情况下,一个cookie的生命周期就是在浏览器关闭的时候结束。如果希望cookie能在浏览器关掉之后还能够使用,就必须要为该cookie设置有效期。域和路径  cookie存在域和路径的概念。域就是domain的概念,因此不同的域之间不能互相访问cookie。路径就是path的概念,一个网页所创建的cookie只能被与这个网页在同一目录或子目录下的所有网页访问。 代码示例 简单的存取操作 document.cookie = 'username=Hudao';

    以上代码中的'username'表示cookie名称,'Hudao'表示表示这个名称对应的值。假设cookie名称并不存在,那么就是创建一个新的cookie;若存在,则修改这个cookie名称对应的值。如果要多次创建cookie,重复此方法即可。

    设置有效期

    在默认情况下,cookie会在浏览器关闭的时候消除,但可通过expires来设置cookie的有效期。语法如下:

    document.cookie = "name=Hudao;expires=date";

    上面的代码中的date值为GMT(格林威治时间)格式的日期型字符串,生成方式如下:

    var _date = new Date(); _date.setDate(_date.getDate()+30); _date.toGMTString();

    上面的代码可解释为:

    通过new生成一个Date的实例,得到当前的时间。getDate()方法得到当前本地月份中的某一天,接着加上30就是此cookie可在本地保存30天。通过setDate()方法来设置时间;用toGMTString()方法把Date对象转换为字符串,并返回结果 参考

    相关页面

    外部链接

    Document.cookie-MDN

热门总结

  • Web API 108 0 1 发布

    在 canvas 中,TextMetrics 接口表示文本的尺寸,通过 CanvasRenderingContext2D.measureText() 方法创建。

      TextMetrics() 继承层次

    Object.prototype  Function.prototype    TextMetrics

    构造函数

    程序不能直接调用该构造函数,否则将会产生异常。

    属性列表 属性说明-- 方法列表 语法说明-- TextMetrics.prototype 继承层次

    Object.prototype  TextMetrics.prototype

    属性列表 属性说明width只读,double 类型,使用 CSS 像素计算的内联字符串的宽度。基于当前上下文字体考虑。actualBoundingBoxLeft只读,double 类型,平行于基线,从 CanvasRenderingContext2D.textAlign 属性确定的对齐点到文本矩形边界左侧的距离,使用 CSS 像素计算。actualBoundingBoxRight只读,double 类型,平行于基线,从 CanvasRenderingContext2D.textAlign 属性确定的对齐点到文本矩形边界右侧的距离,使用 CSS 像素计算。fontBoundingBoxAscent只读,double 类型,从 CanvasRenderingContext2D.textBaseline 属性标明的水平线到渲染文本的所有字体的矩形最高边界顶部的距离,使用 CSS 像素计算。fontBoundingBoxDescent只读,double 类型,根据从 CanvasRenderingContext2D.textBaseline 属性标明的水平线到渲染文本的所有字体的矩形边界顶部的距离,使用 CSS 像素计算。actualBoundingBoxAscent只读,double 类型,从 CanvasRenderingContext2D.textBaseline 属性标明的水平线到渲染文本的矩形边界顶部的距离,使用 CSS 像素计算。actualBoundingBoxDescent只读,double 类型,从 CanvasRenderingContext2D.textBaseline 属性标明的水平线到渲染文本的矩形边界底部的距离,使用 CSS 像素计算。emHeightAscent只读,double 类型,从 CanvasRenderingContext2D.textBaseline 属性标明的水平线到线框中 em 方块顶部的距离,使用 CSS 像素计算。emHeightDescent只读,double 类型,从 CanvasRenderingContext2D.textBaseline 属性标明的水平线到线框中 em 方块底部的距离,使用 CSS 像素计算。hangingBaseline只读,double 类型,从 CanvasRenderingContext2D.textBaseline 属性标明的水平线到线框的 hanging 基线的距离,使用 CSS 像素计算。alphabeticBaseline只读,double 类型,从 CanvasRenderingContext2D.textBaseline 属性标明的水平线到线框的 alphabetic 基线的距离,使用 CSS 像素计算。ideographicBaseline只读,double 类型,从 CanvasRenderingContext2D.textBaseline 属性标明的水平线到线框的 ideographic 基线的距离,使用 CSS 像素计算。 方法列表 语法说明-- TextMetrics实例

    Object.prototype  TextMetrics.prototype   TextMetrics 实例

    参考

    相关页面

    Object

    外部链接

    TextMetrics-MDN
  • Web API 97 0 1 发布

    DOM简介

    DOM(Document Object Model,文档对象模型)将XML/HTML文档构造成一个层次化的节点树,并提供了一系列的应用程序编程接口,以允许程序或脚本动态的访问和修改文档的内容、结构和样式。

    内容结构

    DOM由W3C进行了标准化,W3C DOM标准中立于平台和语言,分为以下3个部分:

    核心DOM:针对结构化文档的标准模型XML DOM: 针对XML文档的标注模型HTML DOM:针对HTML文档的标准模型 标准化历史

    DOM标准化的历史如下:

    规范化前版本  由各个浏览器自行实现,这个阶段的DOM经常被称为DHTML(Dynamic HTML,动态HTML)DOM级别1规范  发布于1998年10月1日,专注于HTML和XML文档模型DOM级别2规范  发布于2000年11月13日,对DOM级别1添加了样式表对象模型和事件处理模型DOM级别3规范  从2004年开始陆续发布,对DOM级别2作了系列扩展 核心DOM

    核心DOM定义了一个通用性的,以节点为基础的结构化文档模型,DOM文档模型中的所有内容都是节点,整个文档是一个文档根节点。

    基本属性

    节点的基本属性如下:

    nodeType  获取节点的类型。例如 1代表元素节点,2代表属性节点,3代表文本节点,通常这三类节点使用的最为普遍.nodeName  获取节点的名称。如果节点是元素节点,则 nodeName属性返回标签名;如果节点是属性节点,则nodeName属性返回属性的名称;其他节点类型,nodeName属性将返回不同节点类型的不同名称。nodeValue  设置或返回节点的值。如果节点是元素节点或文档节点,nodeValue属性值为null;如果节点是属性节点,nodeValue代表属性的值;如果节点是文本节点,nodeValue代表节点的内容;如果节点是注释节点,nodeValue代表注释的内容 节点类型

    核心DOM规范中定义了以下节点类型:

    类型说明Type值子节点Document(文档节点)表示整个文档(DOM树的根节点)9Element(max.one) ProcessingInstruction Comment DocumentTypeElement(元素节点)表示标签元素1Text ProcessingInstruction Comment CDATASection EntityReferenceAttribute(属性节点)表示元素的属性2Text EntityReferenceText(文本节点)表示元素或属性中的文本内容3无CDATASection(CDATA区段节点)表示文档中的 CDATA 区段4无DocumentFragment(文档片段节点)表示轻量级的Document 对象11Text ProcessingInstruction Comment CDATASection EntityReferenceComment(注释节点)表示注释8无

    其他还有几个,但一般不太用到,在此暂不列出。

    节点层次

    节点树中的节点彼此拥有层级关系:父节点(parent),子节点(child)和同胞节点(sibling)等。父节点拥有子节点,同级的子节点被称为同胞节点。 另外一部分节点如元素节点拥有属性节点. DOM规范为节点提供了以下诸多属性,以用于获取节点的层次关联信息。

    属性说明childNodes获取当前节点的所有子节点(※1)firstChild获取当前节点的第一个子节点(※1)lastChild获取当前节点的最后一个子节点(※1)ownerDocument获取该节点的文档根节点,相当与documentparentNode获取当前节点的父节点previousSibling获取当前节点的前一个同级节点nextSibling获取当前节点的后一个同级节点attributes获取当前元素节点的所有属性节点集合(※2)※1 部分类型的节点如文本节点等没有子节点.※2 仅部分类型的节点如元素节点拥有属性 创建节点 方法说明document.write()这个方法可以把任意字符串插入到文档中document.createElement()创建一个元素节点node.appendChild()将新节点追加到子节点列表的末尾document.createTextNode()创建一个文本节点node.insertBefore()将新节点插入在前面node.replaceChild()将新节点替换旧节点node.cloneNode()复制节点node.removeChild()移除节点 HTML DOM

    HTML DOM定义了一个HTML文档的文档对象模型。

    HTML文档首先是一个XML文档,为简单起见,XML DOM部分也包含在HTML DOM里一并说明。

    HTML文档的主要构成元素是各类HTML标签,HTML文档中的标签对应着元素节点。

    元素属性

    HTML元素的属性有attribute与property两个概念,这两个通常都被翻译成属性,但含义完全不一样。

    attribute是HTML标签属性,设计期在文档中直接记述,运行期可以通过Node的接口方法getAttribute(name)和setAttribute(name,value)进行访问。attribute值只存在文字列类型。而property是JS对象属性,运行期象一般的JS对象访问一样直接元素进行操作。property值拥有各自不同的数据类型。

    通常每个attribute都有一个同名的property,property可以看成是attribute的包装器,同时也对attribute值进行必要的类型转换。

    HTML: <input id="input1" type="checkbox" checked= "checked"/> <input id="input2" type="checkbox" checked= "true"/> JavaScript: console.log(document.getElementById("input1").getAttribute("checked")); // checked console.log(document.getElementById("input1").checked); // true console.log(document.getElementById("input2").getAttribute("checked"); // true 元素事件 事件阶段(Event Phases)

    当一个DOM事件被触发的时候,它并不只是在它的起源对象上触发一次,而是会经历以下三个不同的阶段:

    捕获阶段  事件的第一个阶段是捕获阶段。事件从文档的根节点出发,随着DOM树的结构向事件的目标节点流去。途中经过各个层次的DOM节点,并在各节点上触发捕获事件,直到到达事件的目标节点。捕获阶段的主要任务是建立传播路径,在冒泡阶段,事件会通过这个路径回溯到文档跟节点。目标阶段  捕获阶段结束,即当事件到达目标节点后,事件就进入了目标阶段,事件在目标节点上被触发。冒泡阶段  事件在目标元素上触发后,并不在这个元素上终止。它会随着DOM树一层层向上冒泡,直到到达最外层的根节点。 事件处理

    TODO:待编辑

    事件分类

    TODO:待编辑

    元素样式

    TODO:待编辑

    视口

    TODO:待编辑

  • Web API 97 0 1 发布

    Blob 对象是包含有只读原始数据的类文件对象。Blob 对象中的数据并不一定得是JavaScript 中的原生形式。File 接口基于 Blob,继承了 Blob 的功能,并且扩展支持用户计算机上的本地文件。

    创建 Blob 对象的方法有几种,可以调用 Blob() 构造函数,还可以使用一个已有Blob对象上的 slice() 方法切出另一个 Blob 对象。想要从用户的文件里获取一个Blob对象,请参考File文档。

      Blob() 继承层次

    Object.prototype  
        Function.prototype 
      Blob

    构造函数

    Blob(blobParts[, options])

    返回一个新创建的 Blob 对象,其内容由参数中给定的数组串联组成。

    语法 var b1 = new new Boolean(value) 参数 value 可选的Boolean对象的初始值.。 属性列表 名称语法説明sizeBlob.sizeBlob 对象中所包含数据的大小(字节)。typeBlob.type一个字符串,表明该Blob对象所包含数据的MIME类型。如果类型未知,则该值为空字符串。 方法列表 名称语法説明sliceBlob.slice([start[, end[, contentType]]])返回一个新的 Blob 对象,包含了源 Blob 对象中指定范围内的数据。 Blob.prototype 属性列表

    无相应成员。

    方法列表

    无相应成员。

    Blob实例 继承层次

    Object.prototype  Blob.prototype   Blob 实例

    Blob构造函数用法举

    Blob() 构造函数 允许用其它对象创建一个 Blob 对象。比如,用字符串构建一个 blob:

    var debug = {hello: "world"}; var blob = new Blob([JSON.stringify(debug, null, 2)], {type : 'application/json'}); 使用类型数组和 Blob 创建一个 URL var typedArray = GetTheTypedArraySomehow(); // 传入一个合适的MIME类型 var blob = new Blob([typedArray], {type: "application/octet-binary"}); // 会产生一个类似blob:d3958f5c-0777-0845-9dcf-2cb28783acaf 这样的URL字符串 // 你可以像使用一个普通URL那样使用它,比如用在img.src上。 var url = URL.createObjectURL(blob); 从 Blob 中提取数据 var reader = new FileReader(); reader.addEventListener("loadend", function() { // reader.result contains the contents of blob as a typed array }); reader.readAsArrayBuffer(blob);
  • Web API 91 0 1 发布

    使用FileReader对象,web应用程序可以异步的读取存储在用户计算机上的文件(或者原始数据缓冲)内容,可以使用File对象或者Blob对象来指定所要处理的文件或数据。其中File对象可以是来自用户在一个<input>元素上选择文件后返回的FileList对象,也可以来自拖放操作生成的 DataTransfer对象。

      FileReader() 继承层次

    Object.prototype  Function.prototype    EventTarget     FileReader

    构造函数 语法 new FileReader(); 参数 length  指定数组缓冲区的大小,以字节为单位返回值 一个实例化的拥有特定字节数的ArrayBuffer对象。它的每一个字节的值都是0。 属性列表 属性说明-- 方法列表 语法说明-- FileReader.prototype 继承层次

    Object.prototype   EventTarget.prototype    FileReader.prototype

    属性列表

    从其父级继承的属性请查阅: EventTarget

    属性说明error只读,在读取文件时发生的错误。readyState表明FileReader对象的当前状态. 值为State constants中的一个. 只读result读取到的文件内容.这个属性只在读取操作完成之后才有效,并且数据的格式取决于读取操作是由哪个方法发起的. 只读. 方法列表

    从其父级继承的方法请查阅: EventTarget.

    语法说明abort()中止该读取操作.在返回时,readyState属性的值为DONE.readAsArrayBuffer()开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个ArrayBuffer对象以表示所读取文件的内容.readAsBinaryString()开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含所读取文件的原始二进制数据.readAsDataURL()开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.readAsText()开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个字符串以表示所读取的文件内容. FileReader实例

    Object.prototype   EventTarget.prototype    FileReader.prototype    FileReader 实例

    参考

    相关链接

    ObjectEventTarget

    外部链接

    FileReader-MDN
  • Web API 83 0 1 发布
    概述

    DOM存储(Storage)API是通过sessionStorage对象和localStorage对象来实现的。通过这些对象,WEB应用程序能够把信息存储到客户端,并再以后需要的时候进行获取。

    其中:

    sessionStorage 
    会话存储,其中的数据在页面会话结束时会被自动清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话。localStorage 
    本地存储,其中的数据没有过期时间,在页面会话结束时不会被自动清除。

    DOM存储与cookie的相同点:

    提供了把数据保存到本地的能力,页面刷新或者关掉浏览器后,数据依然存在。只能存字符串数据。

    DOM存储与cookie的不同点:

    存储容量大。虽然不同浏览器的标准可能不一样,主流的一般都在5~10M,远超cookie的4k。数据不会自动发送到服务器,与cookie相比,节省带宽,加快响应速度 代码示例浏览器支持检测

    通过以下代码可以事先检测浏览器是否支持本API。

    if(window.Storage) { //支持此API } else { //不支持此API }

    存取数据

    使用本地DOM存储

    var loSt = window.localStorage; loSt['username'] = 'hudao'; loSt.setItem('jobName', 'wrting'); console.log(loSt.length); //2 console.log(loSt.username + ' job is ' + loSt.jobName); //hudao job is wrting loSt['jobName'] = 'singer'; console.log(loSt.username + ' job is ' +loSt.jobName); //hudao job is singer delete loSt['jobName'];

    使用会话DOM存储

    sessionStorage.setItem('company', 'Hudao');

    上面代码表示访问当前域名的会话DOM存储对象,并使用setItem()访问往里面添加一个数据条目。

    //获得填充公司名称的文本输入框 var company = document.getElementByid('company'); //检测是否存在company键值 if(sessionStorage.getItem('company')) { //将文本框中的值设置成sessionStorage中的company键值 company.value = sessionStorage.getItem('company'); } //添加监听文本输入框的change事件 company.addEventListener("change", function(){ //将文本框的值保存到sessionStorage中的company键值 sessionStorage.setItem("company", company.value); }); 捕获存储异常 

    不同的浏览器,分配给本地存储的空间是不一样的,该存储的空间是整个子域共享的。

    如果当本地存储满了,再进行写数据,将会触发error,因此有时需要捕捉调用setItem()时的错误。

    try{ localStorage.setItem('name', 'hudao'); }catch(e){ console.log('It's cant't write!'); } 清空存储

    调用clear()方法将会清空整个域的数据,包括和当前页面共享一个存储空间的其他页面。

    localStorage.clear(); sessionStorage.clear();
  • Web API 82 0 1 发布

    对象可以用来获取某个文件的信息,还可以用来读取这个文件的内容.通常情况下,File对象是来自用户在一个<input>元素上选择文件后返回的FileList对象,也可以是来自由拖放操作生成的 DataTransfer对象.

      File() 继承层次

    Object.prototype
     Function.prototype
        Blob
         File

    构造函数

    程序不能直接调用该构造函数,否则将会产生异常。

    属性列表 属性说明-- 方法列表 语法说明-- File.prototype 继承层次

    Object.prototype   Blob.prototype    File.prototype

    属性列表

    从其父级继承的属性请查阅: Blob

    属性说明lastModifiedDate只读,jsval类型,当前File对象所引用文件最后修改时间。name只读,当前File对象所引用文件的文件名。size只读,当前File对象所引用文件的文件大小,单位为字节。type只读,当前File对象所引用文件的文件类型(MIME类型)。 方法列表

    从其父级继承的方法请查阅: Blob.

    语法说明-- File实例

    Object.prototype   Blob.prototype    File.prototype    File 实例

    参考

    相关链接

    ObjectBlob

    外部链接

    File-MDN
  • Web API 72 0 1 发布

    获取和设置HTML属性文本 var disabled = nodelib.attr(node,"disabled"); nodelib.attr(node,"disabled",""); 获取和设置DOM对象属性 var disabled = nodelib.prop(node,"disabled"); nodelib.prop(node,"disabled",false); 工具函数列表

    uDOMlib所提供的工具函数之中,有一部分与元素属性相关,下面列出部分函数的源代码实现以供参考。

    attr

    获取或设置元素的attribute(HTML标签属性)值。

    attr: function(node,name, value) { if (value === undefined){ if (typeof name === "object"){ for (var attr in name){ this.attr(node,attr,name[atrr]); } return this; } else { return node[name]; } } else { node[name] = value; return this; } } data

    获取或设置元素给定名称的数据存储的值。

    data: function(node,name, value) { var attrName = 'data-' + name.replace(capitalRE, "-$1").toLowerCase() if (value === undefined){ var data = this.attr(node,attrName,value); return data !== null ? deserializeValue(data) : undefined; } else { return this.attr(node,attrName,value); } } html

    获取或设置元素的Html内容。 html()内部使用DOM节点的innerHTML属性,适用于任意HTML元素。

    html: function(node,html) { if (html === undefined){ return node.innerHTML; } else { this.empty(node); node.innerHTML = html; //TODO:will be checkd return this; } } prop

    获取或设置元素的property(特性)值。 prop()方法返回的是节点作为一个JavaScript对象所拥有的特性(property)值。 与attr()方法不同,prop()返回的值具有其本来的数据类型,如针对<input type=“checkbox”/>元素调用prop(“checked”),其返回值将是Boolean型的true或false。

    prop: function(node,name, value) { name = propMap[name] || name; if (value === undefined){ return node[name]; } else { node[name] = value; return this; } } removeAttr removeAttr: function(node,name) { name.split(' ').forEach(function(attr) { setAttribute(node, attr); }); return this; } text

    获取或设置元素的文本内容。 .text() 方法不能使用在input元素或scripts元素上。 input 或 textarea 需要使用 .val() 方法获取或设置文本值。得到scripts元素的值,使用.html()方法

    text: function(node,text) { if (text === undefined){ return node.textContent; } else { node.textContent = text == null ? '' : '' + text return this; } } val

    获取或设置元素的当前值。 val()方法主要适用于表单元素,如input, select 和 textarea。 如果select元素设置了multiple属性,.val()返回一个包含每个选择项值的数组

    val: function(node,value) { if (value === undefined){ if (node.multiple) { // select multiple values var selectedOptions = this.find(node,"option").filter(function(){ return this.selected }); return this.pluck(selectedOptions,"value"); } else { return node.value; } } else { node.value = value; return this; } }
  • Web API 70 0 1 发布

    背景

    通常,当客户端访问一个网页时,会向Web服务器发送一个HTTP请求,Web服务器接收该请求,并返回响应,客户端在接收到响应后再将信息呈现出来。

    对于那些信息变化不是特别频繁的应用来说,也许不会造成多大的影响,但是对于那些对实时性要求比较高即信息经常变化的应用来说(比如在线游戏,信息推送等),就必须采用某种机制来确保服务器与浏览器间的信息同步。

    在WebSocket规范出来之前,可供选择的机制一般三种:

    轮询(Polling)CometFlash插件 轮询

    这是最早的一种实现实时Web应用的方案,客户端按照一定的时间间隔频繁的向服务器发送请求,来实现服务端与客户端的同步。这种方案十分低效,因为并没有什么机制能确定每次发送的请求都能从服务端获得更新的数据(由于服务器更新数据的延时性,会造成客户端发送很多无用的请求,从而浪费了很多通信资源)。

    comet

    Comet本质上还是轮询,只是对上述轮询的缺点上做了些改进,最大限度的降低无效的网络传输。 Comet又分为长轮询技术和流技术,长轮询技术的实现是,给轮询设置条件(比如设置过期时间),当该条件被触发时再发送请求。流技术通常就是在客户端的页面使用一个隐藏窗口向服务端发出一个长连接请求,服务端响应该请求并不断更新连接状态以保证客户端和服务端的连接不过期,在面对并发量比较大的应用时,采用这一方案会消耗很多服务端的资源。

    Flash 插件

    AdobeFlash通过自己的Socket完成数据交换,JavaScript调用Flash提供的API,来实现数据的实时传输。这种方式比轮询要高效得多,但由于需要使用Flash插件,在一些不支持Flash插件或支持得不好客户端上,仍然不能实现实时需求。

    不管是轮询还是comet,这些技术都不能称之为真正的实时技术,它们只是通过Ajax方式来模拟实时效果,客户端和服务端的每次交互都是一次完整的HTTP协议的传输过程(HTTP头信息作为传输内容),大大增加了应用的信息传输量,而且为了实现这些方案,往往需要构建较为复杂的服务端和客户端的编程实现。总体而言,这些技术是即增加了服务端的负载又增加了编程复杂度。

    针对以上技术的缺陷以及web进一步的高并发和实时性需求的环境下,基于HTML5规范的WebSocket应运而生。

    WebSocket是一个基于TCP协议之上解决客户端和服务端之间双向通信的协议,它能高效的实现实现需求。目前有关实时功能的实现基本上都采用WebSocket来实现。

    实现

    WebSocket的实现分为客户端和服务端两部分,客户端发出WebSocket连接请求,服务端响应,实现类似TCP握手的动作,客户端和服务端可以通过这个连接通道传递消息,这个连接会持续存在直到一方主动关闭连接时为止。

    服务端

    rails 5中引入了一个全新的基于WebSocket的框架—Action Cable,可以很方便的构建实时通知系统。下面简单列一下基础代码,有兴趣的朋友也可以点击后面的参考链接作深入的学习。

    def push_to_client user = User.find(self.user_id) user.following_by_type("User").distinct.pluck("id").each do |uid| ActionCable.server.broadcast "notifications/#{uid}", {id: self.id, notifyType: "createTweet"} end rescue nil end

    扩展链接: https://github.com/rails/actioncable-examples https://www.sitepoint.com/create-a-chat-app-with-rails-5-actioncable-and-devise/

    客户端 // 发布消息 var initWebsocket = function() { var self = this; if (window.UasApp && window.UasApp.cable) { if (!this.notificationChannel) { this.notificationChannel = window.UasApp.cable.subscriptions.create("NotificationsChannel", { connected: function() { console.log("connected ................"); }, received: function(data) { self.trigger("notified", { data: data }); } }); } } }; // 监听消息 var bindNotifications = function() { // 监听websocket发布的消息,构建从关注者过来的内容 var self = this; this.own(runtime.on("notified", function(evt) { var data = evt.data; if (data.notifyType === "createTweet") { self.newTweetIds.push(data.id); self.addToNoti(); } })); };

    要点说明:

    1. 上面的rails代码主要用到了Action Cable模块,目前已整合到rails 5.0版本中,属于rails的一部分,源代码。Action Cable 包含了后台和前端的实现,可以方便的为项目添加基于websocket的通信功能。

    2. 上面的前端代码,主要实现了事件分发的功能,首先定制了action cable提供的received方法,该方法会触发notified事件的执行,然后在各实例DOM中监听notified事件,处理其对应的DOM操作,比如样例中的添加新tweet。

    总结:如果需要在客户端与服务端之间建立极低延迟、近乎即时的连接,则可以使用WebSocket,比如下面的一些实用场景:

    多人在线游戏即时聊天体育赛况直播即时更新社交信息流 参考

    WebSocket basics - WebSocket API - WebSocket MDN