【svg+vml】部分尝试

本文介绍了一种兼容SVG和VML的矢量图形绘制方法,可在不同浏览器中实现一致的绘图效果。通过示例代码展示了如何创建并操作矢量图形,包括直线、折线和椭圆等元素。

  半年前看过国外一个大牛的一个demo,然后自己用他的思路写了一个类似的东西。加了点额外的功能。

  当时主要是为了学习svg的部分api,做着玩。
2011061813473885.png

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Rag Doll</title> <meta name="Author" content="hongru.chen" /> <style _mce_bogus="1"><!-- html { overflow: hidden; } ul,ol { margin: 0; padding: 0; list-style:none; } body { margin: 0px; padding: 0px; background: #222; position: absolute; width: 100%; height: 100%; } #screen { position: absolute; left: 6%; top: 10%; width: 88%; height: 80%; background: #000; overflow: hidden; cursor: default; } .toolbar { position: absolute; padding: 20px; background: #282828; color: #707070; right: 20px; top: 40px; -webkit-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px; } .toolbar label { display: inline-block; min-width: 60px; } .toolbar b { display: inline-block; font-size: 12px; color: #b9a662; min-width: 30px; text-align: center; } #title { position: absolute; font-family: verdana; width: 100%; font-size: 7em; font-weight: bold; color: #181818; text-align: center; z-index:0; } .bar-btn { display:inline-block; background: #707070; color: #b9a662; font-size: 10px; font-weight: bold; text-decoration:none; margin-left: 8px; padding: 2px 4px; -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; } .bar-btn.b {font-size: 12px} .bar-btn:hover { color: #ff3a00; } --></style> <script type="text/javascript"><!-- /* ========== for svg and vml compatible ========== */ var __SVG = false; var __svgNS = false; if (document.createElementNS) { __svgNS = "http://www.w3.org/2000/svg"; __svg = document.createElementNS(__svgNS, "svg"); __SVG = (__svg.x != null); } if (__SVG) { /* ============= SVG ============== */ vectorGraphics = function(o, antialias) { this.canvas = document.createElementNS(__svgNS, "svg"); this.canvas.style.position = "absolute"; o.appendChild(this.canvas); this.createLine = function(w, col, linecap) { var o = document.createElementNS(__svgNS, "line"); o.setAttribute("shape-rendering", antialias?"auto":"optimizeSpeed"); o.setAttribute("stroke-width", Math.round(w)+"px"); if (col) o.setAttribute("stroke", col); if (linecap) o.setAttribute("stroke-linecap", linecap); o.move = function(x1, y1, x2, y2) { this.setAttribute("x1", Math.round(x1) + .5); this.setAttribute("y1", Math.round(y1)); this.setAttribute("x2", Math.round(x2)); this.setAttribute("y2", Math.round(y2)); } o.color = function(c){ this.setAttribute("stroke", c); } o.RGBcolor = function(R, G, B){ this.setAttribute("stroke", "rgb("+Math.round(R)+","+Math.round(G)+","+Math.round(B)+")"); } o.stroke_weight = function(s){ this.setAttribute("stroke-width", Math.round(s)+"px"); } this.canvas.appendChild(o); return o; } this.createPolyline = function(w, points, col, fill) { var o = document.createElementNS(__svgNS, "polyline"); o.setAttribute("shape-rendering", antialias?"auto":"optimizeSpeed"); o.setAttribute("stroke-width", Math.round(w)); if (col) o.setAttribute("stroke", col); o.setAttribute("fill", fill?fill:"none"); if (points) o.setAttribute("points", points); o.move = function(points) { this.setAttribute("points", points); } this.canvas.appendChild(o); return o; } this.createOval = function(diam, filled) { var o = document.createElementNS(__svgNS, "circle"); o.setAttribute("shape-rendering", antialias?"auto":"optimizeSpeed"); o.setAttribute("stroke-width", 0); o.setAttribute("r", Math.round(diam / 2)); o.style.cursor = "pointer"; o.move = function(x1, y1, radius) { this.setAttribute("cx", Math.round(x1)); this.setAttribute("cy", Math.round(y1)); this.setAttribute("r", Math.round(radius)); } o.stroke_color = function(col) { this.setAttribute("stroke", col); } o.fill_color = function(col) { this.setAttribute("fill", col); } o.stroke_weight = function(sw) { this.setAttribute("stroke-width", sw); } this.canvas.appendChild(o); return o; } } } else if (document.createStyleSheet) { /* ============= VML ============== */ vectorGraphics = function(o, antialias) { document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); var style = document.createStyleSheet(); var VMLel = ['line','stroke','polyline','fill','oval']; for (var i=0,l=VMLel.length;i<l;i++) { style.addRule('v\\:'+VMLel[i], "behavior: url(#default#VML);"); style.addRule('v\\:'+VMLel[i], "antialias: "+antialias+";"); } this.canvas = o; this.createLine = function(w, col, linecap) { var o = document.createElement("v:line"); o.strokeweight = Math.round(w)+"px"; if (col) o.strokecolor = col; o.move = function(x1, y1, x2, y2) { this.to = (Math.round(x1) + .5) + "," + Math.round(y1); this.from = Math.round(x2) + "," + Math.round(y2); } o.color = function(c){ this.strokecolor = c; } o.RGBcolor = function(R, G, B){ this.strokecolor = "rgb("+Math.round(R)+","+Math.round(G)+","+Math.round(B)+")"; } o.stroke_weight = function(s){ this.strokeweight = Math.round(s)+"px"; } if (linecap) { s = document.createElement("v:stroke"); s.endcap = linecap; o.appendChild(s); } this.canvas.appendChild(o); return o; } this.createPolyline = function(w, points, col, fill) { var o = document.createElement("v:polyline"); o.strokeweight = Math.round(w)+"px"; if (col) o.strokecolor = col; o.points = points; if (fill) o.fillcolor = fill; else { s = document.createElement("v:fill"); s.on = "false"; o.appendChild(s); } o.move = function(points) { this.points.value = points; } this.canvas.appendChild(o); return o; } this.createOval = function(diam, filled) { var o = document.createElement("v:oval"); var os = o.style; os.position = "absolute"; os.cursor = "pointer"; o.strokeweight = 1; o.filled = filled; os.width = Math.round(diam) + "px"; os.height = Math.round(diam) + "px"; o.move = function(x1, y1, radius) { os.left = Math.round(x1 - radius) + "px"; os.top = Math.round(y1 - radius) + "px"; os.width = Math.round(radius * 2) + "px"; os.height = Math.round(radius * 2) + "px"; } o.stroke_color = function(col) { this.strokecolor = col; } o.fill_color = function(col) { this.fillcolor = col; } o.stroke_weight = function(sw) { this.strokeweight = sw; } this.canvas.appendChild(o); return o; } } } else { /* ==== no script ==== */ vectorGraphics = function(o, i) { return false; } } /* ====== Vector ====== */ var Vector = function (x, y) { this.x = x; this.y = y; }; Vector.prototype.equal = function (v, x, y) { this.x = v.x || x || 0; this.y = v.y || y || 0; }; Vector.prototype.add = function (v, x, y) { this.x += v.x || x || 0; this.y += v.y || y || 0; } /* ====== main ========*/ var RagDoll = function () { //private variables var M = {}, S = {}, D = {}, dolls = [], nodes = [], blood = [], collisions = [], svg, scr, zoom, dragDoll = false; nBlood = 100; //private methods var _ = { $: function (id) {return document.getElementById(id)}, addEvent: function (o, e, f) { o.addEventListener ? o.addEventListener(e, f, false) : o.attachEvent('on'+e, function () {f.call(o)}) }, extend: function (t, s) { for (var p in s) { t[p] = s[p] } return t; }, getPos: function (el) { for (var pos = {x:0, y:0}; el; el = el.offsetParent) { pos.x += el.offsetLeft; pos.y += el.offsetTop; } return pos; }, getStyle : function (p, el) { return el.currentStyle ? el.currentStyle[p] : document.defaultView.getComputedStyle(el, null).getPropertyValue(p); }, randomInt: function (f, t) { return Math.ceil(f - 1 + Math.random()*(t-f)); }, randomColor: function () { var cc = '0123456789abcdef'.split(''), color = '#'; for (var i = 0; i < 6; i ++) { color += cc[_.randomInt(0, 16)]; } return color; } } function initScript () { for (var i=0; i<nBlood; i++) {blood.push(new Blood())} for (var i=0; i<dolls.length; i++) { for (var j=0; j<i; j++) { if (i != j) { // for collosions between dolls var o1 = dolls[i], o2 = dolls[j]; for (var i1 = 0, n1; n1 = o1.nodes[i1++]; ) { for (var i2 = 0, n2; n2 = o2.nodes[i2++]; ) { if (n1.testCol == 1 && n2.testCol == 1) { collisions.push({ n1p: n1.pos, n1o: n1.oBody.pos, n2p: n2.pos, n2o: n2.oBody.pos, n2s: new Vector(0, 0), r : ((n1.size * .5) + (n2.size * .5)) / n1.h2Body, m2 : n1.mass / (n1.mass + n2.mass), m1 : n2.mass / (n1.mass + n2.mass) }) } } } } } } } // Tool Bar function initToolBar () { var bar = document.createElement('div'); bar.className = 'toolbar'; bar.innerHTML = '<ul><li><label>bloody:</label><input class="ck" type="checkbox" checked="true" id="bloody-ck" /></li></li><li><label>gravity:</label><b id="gravity-text"></b><a id="gravity-up" class="bar-btn" href="javascript:;">+</a><a id="gravity-down" class="bar-btn" href="javascript:;">-</a></li><li><label>viscosity:</label><b id="viscosity-text"></b><a id="viscosity-up" class="bar-btn" href="javascript:;">+</a><a id="viscosity-down" class="bar-btn" href="javascript:;">-</a></li><li><label>flexibility:</label><b id="flexibility-text"></b><a id="flexibility-up" class="bar-btn" href="javascript:;">+</a><a id="flexibility-down" class="bar-btn" href="javascript:;">-</a></li><li><label>collision:</label><b id="collision-text"></b><a id="collision-up" class="bar-btn" href="javascript:;">+</a><a id="collision-down" class="bar-btn" href="javascript:;">-</a></li><li><a id="shake" class="bar-btn b" href="javascript:;">shake</a></li></ul>'; scr.appendChild(bar); initBarEvents(); } function pushDolls (x, y, n) { //[node_ind,node_parent_ind,node_length,node_spring_parent_ind,spring_length,node_width,node_mass,node_color,blood_on_off,collisions_on_off] var c0 = _.randomColor(), c1 = _.randomColor(), c2 = _.randomColor(), c3 = _.randomColor(); var dolllist = [ // person [[1,0,3,7,80,10,1, c0, 0, 0], [5,3,20,1,60,8,1, c0, 0, 1], [6,4,20,1,60,8,1, c0, 0, 1], [3,1,20,4,40,10,1, c1, 1, 1], [4,1,20,2,40,10,1, c1, 1, 1], [9,7,30,2,80,8,2, c0, 0, 1], [10,8,30,2,80,8,2, c0, 0, 1], [7,2,30,8,30,13,1, c2, 1, 1], [8,2,30,1,80,13,1, c2, 1, 1], [2,1,30,3,40,20,2, c1, 1, 1], [0,0,35,2,60,35,1, c0, 1, 1], [11,1,1,2,25,0,1, c3, 0, 0], [12,11,25,11,25,5,1, c0, 0, 0]], // rect [[1,2,100*.5,3,141*.5,20,2, c0, 0, 1], [2,3,100*.5,0,141*.5,20,2, c0, 0, 1], [3,0,100*.5,1,141*.5,20,2, c0, 0, 1], [0,1,100*.5,2,141*.5,20,2, c0, 0, 1]], // triangle [[1,2,100*.5,0,141*.5,20,4, c1, 0, 1], [2,0,100*.5,1,141*.5,20,4, c1, 0, 1], [0,1,100*.5,2,141*.5,20,2, c1, 0, 1]], // point [[0,0,10,0,10,_.randomInt(10, 40),.1, _.randomColor(), 0, 2]] ] if (n === undefined) { zoom = S.h/500; dolls.push(new Doll(x, y, [ [1,0,3,7,80,10,1, "#fff", 0, 0], [5,3,20,1,60,8,1, "#fff", 0, 1], [6,4,20,1,60,8,1, "#fff", 0, 1], [3,1,20,4,40,10,1, "#FF7a00", 1, 1], [4,1,20,2,40,10,1, "#FF7a00", 1, 1], [9,7,30,2,80,8,2, "#fff", 0, 1], [10,8,30,2,80,8,2, "#fff", 0, 1], [7,2,30,8,30,13,1, "#333", 1, 1], [8,2,30,1,80,13,1, "#333", 1, 1], [2,1,30,3,40,20,2, "#FF7a00", 1, 1], [0,0,35,2,60,35,1, "#fff", 1, 1], [11,1,1,2,25,0,1, "#da4901", 0, 0], [12,11,25,11,25,5,1, "#fff", 0, 0] ])) } else { while (n > 0) { zoom = Math.random(); var _i = _.randomInt(0, 4), _x = x == 'random' ? Math.random() * S.w : x; _y = y == 'random' ? Math.random() * S.h : y; dolls.push(new Doll(_x, _y, dolllist[_i])); n --; } } } var sking = false; function shakeBox (cb) { if (!sking) { var ol = parseInt(_.getStyle('left', scr), 10), ot = parseInt(_.getStyle('top', scr), 10), dl = 20, dt = 20, f = -1; (function () { if (dl > 0) { sking = true; scr.style['left'] = ol + f*dl + 'px'; f *= -1; dl -= 4; } else if (dt > 0) { sking = true; scr.style['top'] = ot + f*dt + 'px'; f *= -1; dt -= 4; } else { sking = false; scr.style['left'] = ol + 'px'; scr.style['top'] = ot + 'px'; !!cb && cb(); return; } setTimeout(arguments.callee, 100); })() } } function initBarEvents () { var g = { u: _.$('gravity-up'), d: _.$('gravity-down'), t: _.$('gravity-text') }, v = { u: _.$('viscosity-up'), d: _.$('viscosity-down'), t: _.$('viscosity-text') }, f = { u: _.$('flexibility-up'), d: _.$('flexibility-down'), t: _.$('flexibility-text') }, c = { u: _.$('collision-up'), d: _.$('collision-down'), t: _.$('collision-text') }, ck = _.$('bloody-ck'), sk = _.$('shake'); _.addEvent(ck, 'click', function () { RagDoll.eBlood = ck.checked }) _.addEvent(g.u, 'click', function () { RagDoll.gravity += .1; g.t.innerHTML = Math.round(RagDoll.gravity*100)/100 }) _.addEvent(g.d, 'click', function () { RagDoll.gravity -= .1; g.t.innerHTML = Math.round(RagDoll.gravity*100)/100 }) _.addEvent(v.u, 'click', function () { if (RagDoll.viscosity >= 1.1) {alert('viscosity can not be more than '+RagDoll.viscosity+''); return} RagDoll.viscosity += .02; v.t.innerHTML = Math.round(RagDoll.viscosity*100)/100 }) _.addEvent(v.d, 'click', function () { RagDoll.viscosity -= .02; v.t.innerHTML = Math.round(RagDoll.viscosity*100)/100 }) _.addEvent(f.u, 'click', function () { RagDoll.flexibility += .1; f.t.innerHTML = Math.round(RagDoll.flexibility*100)/100}) _.addEvent(f.d, 'click', function () { if (Math.floor(RagDoll.flexibility*10) <= 4) {alert('flexibility can not be lesser than 0.4'); return} RagDoll.flexibility -= .1; f.t.innerHTML = Math.round(RagDoll.flexibility*100)/100}) _.addEvent(c.u, 'click', function () { RagDoll.collision += .05; c.t.innerHTML = Math.round(RagDoll.collision*100)/100 }) _.addEvent(c.d, 'click', function () { RagDoll.collision -= .05; c.t.innerHTML = Math.round(RagDoll.collision*100)/100 }) _.addEvent(sk, 'click', function () {shakeBox(function () {pushDolls('random', 20, _.randomInt(3, 6))})}); g.t.innerHTML = RagDoll.gravity; v.t.innerHTML = RagDoll.viscosity; f.t.innerHTML = RagDoll.flexibility; c.t.innerHTML = RagDoll.collision; } function initEvents () { // mousemove event _.addEvent(document, 'mousemove', function (e) { e = e || window.event; M.x = e.clientX; M.y = e.clientY; }) // mouseup event _.addEvent(document, 'mouseup', function (e) { if (dragDoll && document.releaseCapture) { dragDoll.dragNode.o.releaseCapture(); } scr.style.cursor = 'default'; dragDoll = false; }) resize(); _.addEvent(window, 'resize', resize); } function resize () { S.w = scr.offsetWidth || 0; S.h = scr.offsetHeight || 0; scr.style['left'] = document.body.offsetWidth * .06 + 'px'; scr.style['top'] = document.body.offsetHeight * .1 + 'px'; //S.l = _.getPos(scr).x; //S.t = _.getPos(scr).y; } // -- Blood Constructor var Blood = function () { this.o = svg.createLine(5*zoom, '#f00', 'round'); this.o.move(-99, -99, -99, -99); this.pos = new Vector(0, 0); this.vel = new Vector(0, 0); this.bloody = false; } _.extend(Blood.prototype, { start: function (x, y, vx, vy) { this.pos.equal(false, x, y); this.vel.equal(false, vx, vy); this.bloody = true; }, anim: function () { this.vel.x *= .9; this.vel.y *= .9; this.pos.add(this.vel); if (Math.abs(this.vel.x) + Math.abs(this.vel.y) > 1) { this.o.move(this.pos.x, this.pos.y, this.pos.x+this.vel.x, this.pos.y+this.vel.y) } else { this.o.move(-99, -99, -99, -99); this.bloody = false; } } }) // --- Doll Constructor var Doll = function (x, y, params) { this.nodes = []; this.Node = function (doll, p) { this.parent = doll; this.ind = p[0]; this.oBody = p[1]; this.oSpring = p[3]; this.hBody = p[2]*p[2]*zoom*zoom; this.h2Body = p[2]*zoom; this.hSpring = p[4]*p[4]*zoom*zoom; this.size = p[5]*zoom; this.mass = p[6]; this.bloody = p[8]; this.testCol = p[9]; this.pos = new Vector(x + Math.random(), y); this.old = new Vector(x + Math.random(), y); this.vel = new Vector(0, 0); this.o = svg.createLine(this.size, p[7], 'round'); this.o.style.cursor = 'pointer'; this.o.parent = this; this.s = false; // drag events this.o.onselectstart = function () { return false } this.o.ondrag = function () { return false } this.o.onmousedown = function () { dragDoll = this.parent.parent; dragDoll.dragNode = this.parent; D.x = dragDoll.dragNode.pos.x - M.x; D.y = dragDoll.dragNode.pos.y - M.y; scr.style.cursor = 'pointer'; this.setCapture && this.setCapture(); return false; } //console.log(doll) doll.nodes[this.ind] = this; nodes.push(this); } _.extend(this.Node.prototype, { // blood splash bounce: function (val) { if (this.bloody) { if (this.vel.x*this.vel.x + this.vel.y*this.vel.y > zoom) { for (var i=2; i<2+Math.random(); i+=.25) { if (RagDoll.eBlood) { blood[Math.floor(Math.random()*nBlood)].start(this.pos.x, this.pos.y, .001-this.vel.x*zoom*i, .001-this.vel.y*zoom*i); } } } } this.old.equal(this.pos); return val; }, verlet: function () { this.vel.x = (RagDoll.viscosity * (this.pos.x - this.old.x)) || 1; this.vel.y = (RagDoll.viscosity * (this.pos.y - this.old.y) + RagDoll.gravity) || 1; this.old.equal(this.pos); this.pos.add(this.vel); if (this.testCol) { var size = this.size * .5; if (this.pos.x < size) this.pos.x = this.bounce(size); else if (this.pos.x > S.w - size) this.pos.x = this.bounce(S.w - size); if (this.pos.y < size) this.pos.y = this.bounce(size); else if (this.pos.y > S.h - size) this.pos.y = this.bounce(S.h - size); } if (this != this.oSpring) this.satisfyConstraints(this.oSpring, this.hSpring); if (this != this.oBody) this.satisfyConstraints(this.oBody, this.hBody); }, satisfyConstraints: function (that, len) { var dx = that.pos.x - this.pos.x; var dy = that.pos.y - this.pos.y; var delta = len / (dx * dx + dy * dy + len) - .5; var m1 = (this.mass + that.mass) * RagDoll.flexibility; var m2 = this.mass / m1; m1 = that.mass / m1; this.pos.add(false, -m1 * dx * delta, -m1 * dy * delta); that.pos.add(false, m2 * dx * delta, m2 * dy * delta); }, rendering: function () { /* ---- body ---- */ if (this.size) this.o.move( this.pos.x, this.pos.y, this.oBody.pos.x, this.oBody.pos.y ); /* ---- springs ---- */ if (this.s) this.s.move( this.pos.x, this.pos.y, this.oSpring.pos.x, this.oSpring.pos.y ); } }) /* == create Nodes == */ for (var i = 0, p; p = params[i++];) { new this.Node(this, p) } for (var i = 0, o; o = this.nodes[i++];) { o.oBody = this.nodes[o.oBody]; o.oSpring = this.nodes[o.oSpring]; } } // segments intersection function segmentsIntersection (p1, p2, p3, p4) { var dn = ((p4.y - p3.y) * (p2.x - p1.x)) - ((p4.x - p3.x) * (p2.y - p1.y)); if (dn) { var na = ((p4.x - p3.x) * (p1.y - p3.y)) - ((p4.y - p3.y) * (p1.x - p3.x)); var nb = ((p2.x - p1.x) * (p1.y - p3.y)) - ((p2.y - p1.y) * (p1.x - p3.x)); var ua = na / dn; var ub = nb / dn; if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) return ua; } return false; } // ==== Main Loop var run = function () { if (dragDoll) { dragDoll.dragNode.pos.x += (M.x + D.x - dragDoll.dragNode.pos.x) * .2; dragDoll.dragNode.pos.y += (M.y + D.y - dragDoll.dragNode.pos.y) * .2; } // draw doll for (var i = 0, o; o = nodes[i++]; ) o.verlet(); for (var i = 0, o; o = nodes[i++]; ) o.rendering(); // draw blood for (var i = 0, o; o = blood[i++]; ) o.anim(); // collision between dolls if (RagDoll.collision) { for (var i=0, o; o = collisions[i++]; ) { o.n2s.x = o.n2p.x - (o.n2o.x - o.n2p.x) * o.r; o.n2s.y = o.n2p.y - (o.n2o.y - o.n2p.y) * o.r; var ua = segmentsIntersection(o.n1p, o.n1o, o.n2s, o.n2o); if (ua != false) { var ix = ua * (o.n2o.x - o.n2p.x) * RagDoll.collision; var iy = ua * (o.n2o.y - o.n2p.y) * RagDoll.collision; o.n1o.x -= ix * o.m1; o.n2o.x += ix * o.m2; o.n1o.y -= iy * o.m1; o.n2o.y += iy * o.m2; } } } setTimeout(run, 16); } return { eBlood: true, viscosity : 1, flexibility : 1, gravity : .1, collision : .05, init: function () { _.addEvent(window, 'load', function () { scr = _.$('screen'); initEvents(); svg = new vectorGraphics(scr, true); pushDolls(S.w*.5, S.h*.5) initScript(); initToolBar(); run(); }) } } }(); RagDoll.init(); // --></script> </head> <body> <div id="screen"> <div id="title">Rag Doll</div> </div> </body> </html>

里面有做svg和vml的兼容,所以ie6.0+也ok的,但是效率还是很慢。(画直线,折线,和椭圆)
右上角控制栏里的 “shake”和各种参数都可以点下试试看。

/* ========== for svg and vml compatible ========== */
var __SVG = false;
var __svgNS = false;
if (document.createElementNS) {
	__svgNS = "http://www.w3.org/2000/svg";
	__svg = document.createElementNS(__svgNS, "svg");
	__SVG = (__svg.x != null);
}
if (__SVG) {
	/* ============= SVG ============== */
	vectorGraphics = function(o, antialias) {
		this.canvas = document.createElementNS(__svgNS, "svg");
		this.canvas.style.position = "absolute";
		o.appendChild(this.canvas);
		this.createLine = function(w, col, linecap) {
			var o = document.createElementNS(__svgNS, "line");
			o.setAttribute("shape-rendering", antialias?"auto":"optimizeSpeed");
			o.setAttribute("stroke-width", Math.round(w)+"px");
			if (col) o.setAttribute("stroke", col);
			if (linecap) o.setAttribute("stroke-linecap", linecap);
			o.move = function(x1, y1, x2, y2) {
				this.setAttribute("x1", Math.round(x1) + .5);
				this.setAttribute("y1", Math.round(y1));
				this.setAttribute("x2", Math.round(x2));
				this.setAttribute("y2", Math.round(y2));
			}
			o.color = function(c){ this.setAttribute("stroke", c); }
			o.RGBcolor = function(R, G, B){ this.setAttribute("stroke", "rgb("+Math.round(R)+","+Math.round(G)+","+Math.round(B)+")"); }
			o.stroke_weight = function(s){ this.setAttribute("stroke-width", Math.round(s)+"px"); }
			this.canvas.appendChild(o);
			return o;
		}
		this.createPolyline = function(w, points, col, fill) {
			var o = document.createElementNS(__svgNS, "polyline");
			o.setAttribute("shape-rendering", antialias?"auto":"optimizeSpeed");
			o.setAttribute("stroke-width", Math.round(w));
			if (col) o.setAttribute("stroke", col);
			o.setAttribute("fill", fill?fill:"none");
			if (points) o.setAttribute("points", points);
			o.move = function(points) {
				this.setAttribute("points", points);
			}
			this.canvas.appendChild(o);
			return o;
		}
		this.createOval = function(diam, filled) {
			var o = document.createElementNS(__svgNS, "circle");
			o.setAttribute("shape-rendering", antialias?"auto":"optimizeSpeed");
			o.setAttribute("stroke-width", 0);
			o.setAttribute("r", Math.round(diam / 2));
			o.style.cursor = "pointer";
			o.move = function(x1, y1, radius) {
				this.setAttribute("cx", Math.round(x1));
				this.setAttribute("cy", Math.round(y1));
				this.setAttribute("r", Math.round(radius));
			}
			o.stroke_color = function(col) { this.setAttribute("stroke", col); }
			o.fill_color = function(col) { this.setAttribute("fill", col); }
			o.stroke_weight = function(sw) { this.setAttribute("stroke-width", sw); }
			this.canvas.appendChild(o);
			return o;
		}
	}
	
} else if (document.createStyleSheet) {
	/* ============= VML ============== */
	vectorGraphics = function(o, antialias) {
		document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
		var style = document.createStyleSheet();
		var VMLel = ['line','stroke','polyline','fill','oval'];
		for (var i=0,l=VMLel.length;i<l;i++) {
			style.addRule('v\\:'+VMLel[i], "behavior: url(#default#VML);");
			style.addRule('v\\:'+VMLel[i], "antialias: "+antialias+";");
		}
		this.canvas = o;
		this.createLine = function(w, col, linecap) {
			var o = document.createElement("v:line");
			o.strokeweight = Math.round(w)+"px";
			if (col) o.strokecolor = col;
			o.move = function(x1, y1, x2, y2) {
				this.to   = (Math.round(x1) + .5) + "," + Math.round(y1);
				this.from = Math.round(x2) + "," + Math.round(y2);
			}
			o.color = function(c){ this.strokecolor = c; }
			o.RGBcolor = function(R, G, B){ this.strokecolor = "rgb("+Math.round(R)+","+Math.round(G)+","+Math.round(B)+")"; }
			o.stroke_weight = function(s){ this.strokeweight = Math.round(s)+"px"; }
			if (linecap) {
				s = document.createElement("v:stroke");
				s.endcap = linecap;
				o.appendChild(s);
			}
			this.canvas.appendChild(o);
			return o;
		}
		this.createPolyline = function(w, points, col, fill) {
			var o = document.createElement("v:polyline");
			o.strokeweight = Math.round(w)+"px";
			if (col) o.strokecolor = col;
			o.points = points;
			if (fill) o.fillcolor = fill;
			else {
				s = document.createElement("v:fill");
				s.on = "false";
				o.appendChild(s);
			}
			o.move = function(points) {
				this.points.value = points;
			}
			this.canvas.appendChild(o);
			return o;
		}
		this.createOval = function(diam, filled) {
			var o = document.createElement("v:oval");
			var os = o.style;
			os.position = "absolute";
			os.cursor = "pointer";
			o.strokeweight = 1;
			o.filled = filled;
			os.width = Math.round(diam) + "px";
			os.height = Math.round(diam) + "px";
			o.move = function(x1, y1, radius) {
				os.left   = Math.round(x1 - radius) + "px";
				os.top    = Math.round(y1 - radius) + "px";
				os.width  = Math.round(radius * 2) + "px";
				os.height = Math.round(radius * 2) + "px";
			}
			o.stroke_color = function(col) { this.strokecolor = col; }
			o.fill_color = function(col) { this.fillcolor = col; }
			o.stroke_weight = function(sw) { this.strokeweight = sw; }
			this.canvas.appendChild(o);
			return o;
		}
	}
} else {
	/* ==== no script ==== */
	vectorGraphics = function(o, i) {
		return false;
	}
}
  关于画矢量图(直线,折线,圆),下面是个简单的演示,利用上面的代码:
  <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <script type="text/javascript"><!-- /* ========== for svg and vml compatible ========== */ var __SVG = false; var __svgNS = false; if (document.createElementNS) { __svgNS = "http://www.w3.org/2000/svg"; __svg = document.createElementNS(__svgNS, "svg"); __SVG = (__svg.x != null); } if (__SVG) { /* ============= SVG ============== */ vectorGraphics = function(o, antialias) { this.canvas = document.createElementNS(__svgNS, "svg"); this.canvas.style.position = "absolute"; o.appendChild(this.canvas); this.createLine = function(w, col, linecap) { var o = document.createElementNS(__svgNS, "line"); o.setAttribute("shape-rendering", antialias?"auto":"optimizeSpeed"); o.setAttribute("stroke-width", Math.round(w)+"px"); if (col) o.setAttribute("stroke", col); if (linecap) o.setAttribute("stroke-linecap", linecap); o.move = function(x1, y1, x2, y2) { this.setAttribute("x1", Math.round(x1) + .5); this.setAttribute("y1", Math.round(y1)); this.setAttribute("x2", Math.round(x2)); this.setAttribute("y2", Math.round(y2)); } o.color = function(c){ this.setAttribute("stroke", c); } o.RGBcolor = function(R, G, B){ this.setAttribute("stroke", "rgb("+Math.round(R)+","+Math.round(G)+","+Math.round(B)+")"); } o.stroke_weight = function(s){ this.setAttribute("stroke-width", Math.round(s)+"px"); } this.canvas.appendChild(o); return o; } this.createPolyline = function(w, points, col, fill) { var o = document.createElementNS(__svgNS, "polyline"); o.setAttribute("shape-rendering", antialias?"auto":"optimizeSpeed"); o.setAttribute("stroke-width", Math.round(w)); if (col) o.setAttribute("stroke", col); o.setAttribute("fill", fill?fill:"none"); if (points) o.setAttribute("points", points); o.move = function(points) { this.setAttribute("points", points); } this.canvas.appendChild(o); return o; } this.createOval = function(diam, filled) { var o = document.createElementNS(__svgNS, "circle"); o.setAttribute("shape-rendering", antialias?"auto":"optimizeSpeed"); o.setAttribute("stroke-width", 1); o.setAttribute("r", Math.round(diam / 2)); o.setAttribute("fill", filled); o.style.cursor = "pointer"; o.move = function(x1, y1, radius) { this.setAttribute("cx", Math.round(x1)); this.setAttribute("cy", Math.round(y1)); this.setAttribute("r", Math.round(radius)); } o.stroke_color = function(col) { this.setAttribute("stroke", col); } o.fill_color = function(col) { this.setAttribute("fill", col); } o.stroke_weight = function(sw) { this.setAttribute("stroke-width", sw); } this.canvas.appendChild(o); return o; } } } else if (document.createStyleSheet) { /* ============= VML ============== */ vectorGraphics = function(o, antialias) { document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); var style = document.createStyleSheet(); var VMLel = ['line','stroke','polyline','fill','oval']; for (var i=0,l=VMLel.length;i<l;i++) { style.addRule('v\\:'+VMLel[i], "behavior: url(#default#VML);"); style.addRule('v\\:'+VMLel[i], "antialias: "+antialias+";"); } this.canvas = o; this.createLine = function(w, col, linecap) { var o = document.createElement("v:line"); o.strokeweight = Math.round(w)+"px"; if (col) o.strokecolor = col; o.move = function(x1, y1, x2, y2) { this.to = (Math.round(x1) + .5) + "," + Math.round(y1); this.from = Math.round(x2) + "," + Math.round(y2); } o.color = function(c){ this.strokecolor = c; } o.RGBcolor = function(R, G, B){ this.strokecolor = "rgb("+Math.round(R)+","+Math.round(G)+","+Math.round(B)+")"; } o.stroke_weight = function(s){ this.strokeweight = Math.round(s)+"px"; } if (linecap) { s = document.createElement("v:stroke"); s.endcap = linecap; o.appendChild(s); } this.canvas.appendChild(o); return o; } this.createPolyline = function(w, points, col, fill) { var o = document.createElement("v:polyline"); o.strokeweight = Math.round(w)+"px"; if (col) o.strokecolor = col; o.points = points; if (fill) o.fillcolor = fill; else { s = document.createElement("v:fill"); s.on = "false"; o.appendChild(s); } o.move = function(points) { this.points.value = points; } this.canvas.appendChild(o); return o; } this.createOval = function(diam, filled) { var o = document.createElement("v:oval"); var os = o.style; os.position = "absolute"; os.cursor = "pointer"; o.strokeweight = 0; o.filled = filled; o.fillcolor = filled; os.width = Math.round(diam) + "px"; os.height = Math.round(diam) + "px"; o.move = function(x1, y1, radius) { os.left = Math.round(x1 - radius) + "px"; os.top = Math.round(y1 - radius) + "px"; os.width = Math.round(radius * 2) + "px"; os.height = Math.round(radius * 2) + "px"; } o.stroke_color = function(col) { this.strokecolor = col; } o.fill_color = function(col) { this.fillcolor = col; } o.stroke_weight = function(sw) { this.strokeweight = sw; } this.canvas.appendChild(o); return o; } } } else { /* ==== no script ==== */ vectorGraphics = function(o, i) { return false; } } // --></script> <style _mce_bogus="1"><!-- #screen { height: 400px; background: #f3f3f3; width: 80%; margin: 20px 10%; border: 1px solid #d5d5d5; } .hide{display:none} --></style> </head> <body> <div id="screen"></div> <input id="draw-line" type="button" value="绘制矢量图" /> <input id="rotate-line" class="hide" type="button" value="变换" /> <script type="text/javascript"><!-- var addEvent = function (o, e, f) { o.addEventListener ? o.addEventListener(e, f, false) : o.attachEvent('on'+e, function () {f.call(o)}); }, $ = function (id) { return document.getElementById(id) } onload = function () { var scr = document.getElementById('screen'), svg = new vectorGraphics(scr, true), dl = $('draw-line'), rl = $('rotate-line'); var Line = function (weight, color, r) { this.o = svg.createLine(weight, color, 'round'); this.pl = svg.createPolyline(2, '', color, '#d8e'); this.c = svg.createOval(0, color); this.a = 0; this.r = r; this.pos = {x: 20, y: 30}; this.pos2 = {x: 400, y: 100}; } Line.prototype = { show: function () { this.o.move(this.r*(1+Math.sin(this.a))+this.pos.x, this.r*(1-Math.cos(this.a))+this.pos.y, this.r*(1-Math.sin(this.a))+this.pos.x, this.r*(1+Math.cos(this.a))+this.pos.y); this.pl.move(''+(this.pos2.x-this.r*Math.sin(30+this.a))+','+(this.pos2.y-this.r*Math.cos(30+this.a))+' '+(this.pos2.x+this.r*Math.sin(30+this.a))+','+(this.pos2.y-this.r*Math.cos(30+this.a))+' '+(this.pos2.x+this.r*Math.sin(this.a))+','+(this.pos2.y+this.r*Math.cos(this.a))+''); this.c.move(800, 160, this.r*(Math.cos(this.a)+1.5)/2); }, rotate: function () { var _this = this; this._interval = setInterval(function () { _this.show(); _this.a += .1; }, 16) }, stop: function () { clearInterval(this._interval) } } var line = new Line(10, '#da4901', 80); addEvent(dl, 'click', function () { line.show(); rl.style['display'] = 'inline' }); addEvent(rl, 'click', function () { if (this.value == '变换') { line.rotate(); this.value = '停止'; } else if (this.value == '停止') { line.stop(); this.value = '变换'; } }) } // --></script> </body> </html>

在做浏览器适配的时候,某些情况下不得不考虑ie低版本的兼容时,其实svg+vml在矢量图方面算个不错的选择。

利用上面的直线和圆,其实就可以做个时钟了。: )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值