?? vml.js
字號:
/* Copyright (c) 2004-2006, The Dojo Foundation All Rights Reserved. Licensed under the Academic Free License version 2.1 or above OR the modified BSD license. For more information on Dojo licensing, see: http://dojotoolkit.org/community/licensing.shtml*/dojo.provide("dojo.gfx.vml");dojo.require("dojo.dom");dojo.require("dojo.math");dojo.require("dojo.lang.declare");dojo.require("dojo.lang.extras");dojo.require("dojo.string.*");dojo.require("dojo.html.metrics");dojo.require("dojo.gfx.color");dojo.require("dojo.gfx.common");dojo.require("dojo.gfx.shape");dojo.require("dojo.gfx.path");dojo.require("dojo.experimental");dojo.experimental("dojo.gfx.vml");// dojo.gfx.vml.xmlns: String: a VML's namespacedojo.gfx.vml.xmlns = "urn:schemas-microsoft-com:vml";dojo.gfx.vml._parseFloat = function(str) { // summary: a helper function to parse VML-specific floating-point values // str: String: a representation of a floating-point number return str.match(/^\d+f$/i) ? parseInt(str) / 65536 : parseFloat(str); // Number};// dojo.gfx.vml.cm_in_pt: Number: centimeters per inchdojo.gfx.vml.cm_in_pt = 72 / 2.54;// dojo.gfx.vml.mm_in_pt: Number: millimeters per inchdojo.gfx.vml.mm_in_pt = 7.2 / 2.54;dojo.gfx.vml.px_in_pt = function(){ // summary: returns a number of pixels per point return dojo.html.getCachedFontMeasurements()["12pt"] / 12; // Number};dojo.gfx.vml.pt2px = function(len){ // summary: converts points to pixels // len: Number: a value in points return len * this.px_in_pt(); // Number};dojo.gfx.vml.px2pt = function(len){ // summary: converts pixels to points // len: Number: a value in pixels return len / this.px_in_pt(); // Number};dojo.gfx.vml.normalizedLength = function(len) { // summary: converts any length value to points // len: String: a length, e.g., "12pc" if(len.length == 0) return 0; if(len.length > 2){ var px_in_pt = this.px_in_pt(); var val = parseFloat(len); switch(len.slice(-2)){ case "px": return val; case "pt": return val * px_in_pt; case "in": return val * 72 * px_in_pt; case "pc": return val * 12 * px_in_pt; case "mm": return val / this.mm_in_pt * px_in_pt; case "cm": return val / this.cm_in_pt * px_in_pt; } } return parseFloat(len); // Number};dojo.lang.extend(dojo.gfx.Shape, { // summary: VML-specific implementation of dojo.gfx.Shape methods setFill: function(fill){ // summary: sets a fill object (VML) // fill: Object: a fill object // (see dojo.gfx.defaultLinearGradient, // dojo.gfx.defaultRadialGradient, // dojo.gfx.defaultPattern, // or dojo.gfx.color.Color) if(!fill){ // don't fill this.fillStyle = null; this.rawNode.filled = false; return this; } if(typeof(fill) == "object" && "type" in fill){ // gradient switch(fill.type){ case "linear": var f = dojo.gfx.makeParameters(dojo.gfx.defaultLinearGradient, fill); this.fillStyle = f; var s = ""; for(var i = 0; i < f.colors.length; ++i){ f.colors[i].color = dojo.gfx.normalizeColor(f.colors[i].color); s += f.colors[i].offset.toFixed(8) + " " + f.colors[i].color.toHex() + ";"; } var fo = this.rawNode.fill; fo.colors.value = s; fo.method = "sigma"; fo.type = "gradient"; fo.angle = (dojo.math.radToDeg(Math.atan2(f.x2 - f.x1, f.y2 - f.y1)) + 180) % 360; fo.on = true; break; case "radial": var f = dojo.gfx.makeParameters(dojo.gfx.defaultRadialGradient, fill); this.fillStyle = f; var w = parseFloat(this.rawNode.style.width); var h = parseFloat(this.rawNode.style.height); var c = isNaN(w) ? 1 : 2 * f.r / w; var i = f.colors.length - 1; f.colors[i].color = dojo.gfx.normalizeColor(f.colors[i].color); var s = "0 " + f.colors[i].color.toHex(); for(; i >= 0; --i){ f.colors[i].color = dojo.gfx.normalizeColor(f.colors[i].color); s += (1 - c * f.colors[i].offset).toFixed(8) + " " + f.colors[i].color.toHex() + ";"; } var fo = this.rawNode.fill; fo.colors.value = s; fo.method = "sigma"; fo.type = "gradientradial"; if(isNaN(w) || isNaN(h)){ fo.focusposition = "0.5 0.5"; }else{ fo.focusposition = (f.cx / w).toFixed(8) + " " + (f.cy / h).toFixed(8); } fo.focussize = "0 0"; fo.on = true; break; case "pattern": var f = dojo.gfx.makeParameters(dojo.gfx.defaultPattern, fill); this.fillStyle = f; var fo = this.rawNode.fill; fo.type = "tile"; fo.src = f.src; if(f.width && f.height){ // in points fo.size.x = dojo.gfx.vml.px2pt(f.width); fo.size.y = dojo.gfx.vml.px2pt(f.height); } fo.alignShape = false; fo.position.x = 0; fo.position.y = 0; fo.origin.x = f.width ? f.x / f.width : 0; fo.origin.y = f.height ? f.y / f.height : 0; fo.on = true; break; } this.rawNode.fill.opacity = 1; return this; } // color object this.fillStyle = dojo.gfx.normalizeColor(fill); this.rawNode.fillcolor = this.fillStyle.toHex(); this.rawNode.fill.opacity = this.fillStyle.a; this.rawNode.filled = true; return this; // self }, setStroke: function(stroke){ // summary: sets a stroke object (VML) // stroke: Object: a stroke object // (see dojo.gfx.defaultStroke) if(!stroke){ // don't stroke this.strokeStyle = null; this.rawNode.stroked = false; return this; } // normalize the stroke this.strokeStyle = dojo.gfx.makeParameters(dojo.gfx.defaultStroke, stroke); this.strokeStyle.color = dojo.gfx.normalizeColor(this.strokeStyle.color); // generate attributes var s = this.strokeStyle; this.rawNode.stroked = true; this.rawNode.strokecolor = s.color.toCss(); this.rawNode.strokeweight = s.width + "px"; // TODO: should we assume that the width is always in pixels? if(this.rawNode.stroke) { this.rawNode.stroke.opacity = s.color.a; this.rawNode.stroke.endcap = this._translate(this._capMap, s.cap); if(typeof(s.join) == "number") { this.rawNode.stroke.joinstyle = "miter"; this.rawNode.stroke.miterlimit = s.join; }else{ this.rawNode.stroke.joinstyle = s.join; // this.rawNode.stroke.miterlimit = s.width; } } return this; // self }, _capMap: { butt: 'flat' }, _capMapReversed: { flat: 'butt' }, _translate: function(dict, value) { return (value in dict) ? dict[value] : value; }, _applyTransform: function() { var matrix = this._getRealMatrix(); if(!matrix) return this; var skew = this.rawNode.skew; if(typeof(skew) == "undefined"){ for(var i = 0; i < this.rawNode.childNodes.length; ++i){ if(this.rawNode.childNodes[i].tagName == "skew"){ skew = this.rawNode.childNodes[i]; break; } } } if(skew){ skew.on = false; var mt = matrix.xx.toFixed(8) + " " + matrix.xy.toFixed(8) + " " + matrix.yx.toFixed(8) + " " + matrix.yy.toFixed(8) + " 0 0"; var offset = Math.floor(matrix.dx).toFixed() + "px " + Math.floor(matrix.dy).toFixed() + "px"; var l = parseFloat(this.rawNode.style.left); var t = parseFloat(this.rawNode.style.top); var w = parseFloat(this.rawNode.style.width); var h = parseFloat(this.rawNode.style.height); if(isNaN(l)) l = 0; if(isNaN(t)) t = 0; if(isNaN(w)) w = 1; if(isNaN(h)) h = 1; var origin = (-l / w - 0.5).toFixed(8) + " " + (-t / h - 0.5).toFixed(8); skew.matrix = mt; skew.origin = origin; skew.offset = offset; skew.on = true; } return this; }, setRawNode: function(rawNode){ // summary: // assigns and clears the underlying node that will represent this // shape. Once set, transforms, gradients, etc, can be applied. // (no fill & stroke by default) rawNode.stroked = false; rawNode.filled = false; this.rawNode = rawNode; }, // Attach family attachFill: function(rawNode){ // summary: deduces a fill style from a Node. // rawNode: Node: an VML node var fillStyle = null; var fo = rawNode.fill; if(rawNode) { if(fo.on && fo.type == "gradient"){ var fillStyle = dojo.lang.shallowCopy(dojo.gfx.defaultLinearGradient, true); var rad = dojo.math.degToRad(fo.angle); fillStyle.x2 = Math.cos(rad); fillStyle.y2 = Math.sin(rad); fillStyle.colors = []; var stops = fo.colors.value.split(";"); for(var i = 0; i < stops.length; ++i){ var t = stops[i].match(/\S+/g); if(!t || t.length != 2) continue; fillStyle.colors.push({offset: dojo.gfx.vml._parseFloat(t[0]), color: new dojo.gfx.color.Color(t[1])}); } }else if(fo.on && fo.type == "gradientradial"){ var fillStyle = dojo.lang.shallowCopy(dojo.gfx.defaultRadialGradient, true); var w = parseFloat(rawNode.style.width); var h = parseFloat(rawNode.style.height); fillStyle.cx = isNaN(w) ? 0 : fo.focusposition.x * w; fillStyle.cy = isNaN(h) ? 0 : fo.focusposition.y * h; fillStyle.r = isNaN(w) ? 1 : w / 2; fillStyle.colors = []; var stops = fo.colors.value.split(";"); for(var i = stops.length - 1; i >= 0; --i){ var t = stops[i].match(/\S+/g); if(!t || t.length != 2) continue; fillStyle.colors.push({offset: dojo.gfx.vml._parseFloat(t[0]), color: new dojo.gfx.color.Color(t[1])}); } }else if(fo.on && fo.type == "tile"){ var fillStyle = dojo.lang.shallowCopy(dojo.gfx.defaultPattern, true); fillStyle.width = dojo.gfx.vml.pt2px(fo.size.x); // from pt fillStyle.height = dojo.gfx.vml.pt2px(fo.size.y); // from pt fillStyle.x = fo.origin.x * fillStyle.width; fillStyle.y = fo.origin.y * fillStyle.height; fillStyle.src = fo.src; }else if(fo.on && rawNode.fillcolor){ // a color object ! fillStyle = new dojo.gfx.color.Color(rawNode.fillcolor+""); fillStyle.a = fo.opacity; } } return fillStyle; // Object }, attachStroke: function(rawNode) { // summary: deduces a stroke style from a Node. // rawNode: Node: an VML node var strokeStyle = dojo.lang.shallowCopy(dojo.gfx.defaultStroke, true); if(rawNode && rawNode.stroked){ strokeStyle.color = new dojo.gfx.color.Color(rawNode.strokecolor.value); dojo.debug("We are expecting an .75pt here, instead of strokeweight = " + rawNode.strokeweight ); strokeStyle.width = dojo.gfx.vml.normalizedLength(rawNode.strokeweight+""); strokeStyle.color.a = rawNode.stroke.opacity; strokeStyle.cap = this._translate(this._capMapReversed, rawNode.stroke.endcap); strokeStyle.join = rawNode.stroke.joinstyle == "miter" ? rawNode.stroke.miterlimit : rawNode.stroke.joinstyle; }else{ return null; } return strokeStyle; // Object }, attachTransform: function(rawNode) { // summary: deduces a transformation matrix from a Node. // rawNode: Node: an VML node var matrix = {}; if(rawNode){ var s = rawNode.skew; matrix.xx = s.matrix.xtox; matrix.xy = s.matrix.ytox; matrix.yx = s.matrix.xtoy; matrix.yy = s.matrix.ytoy; matrix.dx = dojo.gfx.vml.pt2px(s.offset.x); matrix.dy = dojo.gfx.vml.pt2px(s.offset.y); } return dojo.gfx.matrix.normalize(matrix); // dojo.gfx.matrix.Matrix }, attach: function(rawNode){ // summary: reconstructs all shape parameters from a Node. // rawNode: Node: an VML node if(rawNode){ this.rawNode = rawNode; this.shape = this.attachShape(rawNode); this.fillStyle = this.attachFill(rawNode); this.strokeStyle = this.attachStroke(rawNode); this.matrix = this.attachTransform(rawNode); } }});dojo.declare("dojo.gfx.Group", dojo.gfx.shape.VirtualGroup, { // summary: a group shape (VML), which can be used // to logically group shapes (e.g, to propagate matricies) add: function(shape){ // summary: adds a shape to a group/surface // shape: dojo.gfx.Shape: an VML shape object if(this != shape.getParent()){ this.rawNode.appendChild(shape.rawNode); dojo.gfx.Group.superclass.add.apply(this, arguments); } return this; // self }, remove: function(shape, silently){ // summary: remove a shape from a group/surface // shape: dojo.gfx.Shape: an VML shape object // silently: Boolean?: if true, regenerate a picture if(this == shape.getParent()){ if(this.rawNode == shape.rawNode.parentNode){ this.rawNode.removeChild(shape.rawNode); } dojo.gfx.Group.superclass.remove.apply(this, arguments); } return this; // self }, attach: function(rawNode){ // summary: reconstructs all group shape parameters from a Node (VML). // rawNode: Node: a node if(rawNode){ this.rawNode = rawNode; this.shape = null; this.fillStyle = null; this.strokeStyle = null; this.matrix = null; } }});dojo.gfx.Group.nodeType = "group";var zIndex = { moveToFront: function(){ // summary: moves a shape to front of its parent's list of shapes (VML) this.rawNode.parentNode.appendChild(this.rawNode); return this; }, moveToBack: function(){ // summary: moves a shape to back of its parent's list of shapes (VML) this.rawNode.parentNode.insertBefore(this.rawNode, this.rawNode.parentNode.firstChild); return this; }};dojo.lang.extend(dojo.gfx.Shape, zIndex);dojo.lang.extend(dojo.gfx.Group, zIndex);delete zIndex;dojo.declare("dojo.gfx.Rect", dojo.gfx.shape.Rect, { // summary: a rectangle shape (VML) attachShape: function(rawNode){ // summary: builds a rectangle shape from a Node. // rawNode: Node: a VML node // a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated node var arcsize = rawNode.outerHTML.match(/arcsize = \"(\d*\.?\d+[%f]?)\"/)[1]; arcsize = (arcsize.indexOf("%") >= 0) ? parseFloat(arcsize) / 100 : dojo.gfx.vml._parseFloat(arcsize); var style = rawNode.style; var width = parseFloat(style.width); var height = parseFloat(style.height); // make an object var o = dojo.gfx.makeParameters(dojo.gfx.defaultRect, { x: parseInt(style.left), y: parseInt(style.top), width: width, height: height, r: Math.min(width, height) * arcsize }); return o; // dojo.gfx.shape.Rect }, setShape: function(newShape){ // summary: sets a rectangle shape object (VML) // newShape: Object: a rectangle shape object var shape = this.shape = dojo.gfx.makeParameters(this.shape, newShape); this.bbox = null; var style = this.rawNode.style; style.left = shape.x.toFixed(); style.top = shape.y.toFixed(); style.width = (typeof(shape.width) == "string" && shape.width.indexOf("%") >= 0) ? shape.width : shape.width.toFixed(); style.height = (typeof(shape.width) == "string" && shape.height.indexOf("%") >= 0) ? shape.height : shape.height.toFixed(); var r = Math.min(1, (shape.r / Math.min(parseFloat(shape.width), parseFloat(shape.height)))).toFixed(8); // a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated node var parent = this.rawNode.parentNode; var before = null; if(parent){ if(parent.lastChild != this.rawNode){ for(var i = 0; i < parent.childNodes.length; ++i){
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -