svg射线学习
<!DOCTYPE html> <html> <head> <title>百度招聘首页射线地图效果</title> <meta charset="utf-8" /> <style type="text/css"> * { margin: 0; padding: 0; } html { height: 100%; width: 100%; overflow: hidden; } body { height: 100%; width: 100%; background-color: cadetblue; } </style> <script type="text/javascript"> function RayMap(svg, configObj, isRelative) { svg.setAttribute("height", '100%'); svg.setAttribute("width", '100%'); svg.setAttribute("style", 'position:absolute;left:0;top:0;'); var HEIGHT = svg.clientHeight || svg.parentElement.clientHeight; var WIDTH = svg.clientWidth || svg.parentElement.clientWidth; // Tool function var EventUtil = { //添加事件处理函数 addHandler: function (element, type, handler) { if (element.addEventListener) { element.addEventListener(type, handler, false); } else if (element.attachEvent) { element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } } }; function createSvgElement(name) { return document.createElementNS('http://www.w3.org/2000/svg', name); } function getSpeed(beginPoint, endPoint, time) { return { X: (endPoint.x - beginPoint.x) / time, Y: (endPoint.y - beginPoint.y) / time }; } function changeAllColor(arr, opacity) { for (var i = 1; i < arr.length; i++) { arr[i].changeOpacity(opacity); } } function createPointStr(pointArr) { var strArr = []; for (var i = 0; i < pointArr.length; i++) { strArr.push(pointArr[i].x + ',' + pointArr[i].y); } return strArr.join(' '); } function changeAllxy(obj) { for (var i in obj) { if (typeof (obj[i]) == 'object') { changeAllxy(obj[i]); } else { if (i == 'x') { obj[i] = obj[i] * WIDTH; } else if (i == 'y') { obj[i] = obj[i] * HEIGHT; } } } } function recoverAllxy(obj) { for (var i in obj) { if (typeof (obj[i]) == 'object') { recoverAllxy(obj[i]); } else { if (i == 'x') { obj[i] = obj[i] / WIDTH; } else if (i == 'y') { obj[i] = obj[i] / HEIGHT; } } } } function getOtherPointsPos(obj) { } Array.prototype.clone = function () { return this.slice(0); } // cross-browser requestAnimFrame window.requestAnimationFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); }; })(); // cross-browser requestAnimFrame window.cancelAnimationFrame = (function () { return window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || function (requestID) { window.clearTimeout(requestID); }; })(); // Point class function Point(x, y, r, color, isLink) { this.r = r; this.color = color; this.isLink = isLink; this.x = x; this.y = y; } Point.prototype.draw = function () { this.circle = createSvgElement('circle'); this.circle.setAttribute("cx", this.x); this.circle.setAttribute("cy", this.y); this.circle.setAttribute("r", this.r); this.circle.style.fill = this.color; svg.appendChild(this.circle); } Point.prototype.changeOpacity = function (opacity) { this.circle.style.fill = this.color.slice(0, 17) + opacity + ')'; } //for diffuse animation (Wave class) Point.prototype.gradual = function (x, y, width, step) { this.circle.setAttribute('cx', x); this.circle.setAttribute('cy', y); var progress = 0; var temp = { opacity: 0, r: 0 } var speed = { spOp1: 1 / (step * 0.05), spOp2: -1 / (step * 0.95), spR: width / step }; var drawRun = function () { progress++; this.circle.setAttribute("r", temp.r); this.circle.setAttribute("opacity", temp.opacity); temp.r += speed.spR; temp.opacity += (progress <= step * 0.05 ? speed.spOp1 : speed.spOp2); if (progress <= step) { this.requestID = requestAnimationFrame(drawRun); } else if (progress >= step) { progress = 0; temp = { opacity: 0, r: 0 } this.requestID = requestAnimationFrame(drawRun); } else { this.circle.setAttribute("r", 0); this.circle.setAttribute("opacity", 0); } }.bind(this); return drawRun; } // Wave class function Wave() { this.wave1 = new Point(0, 0, 0, 'rgba(255,255,255,0.4)'); this.wave2 = new Point(0, 0, 0, 'rgba(255,255,255,0.4)'); this.wave1.draw(); this.wave2.draw(); } //Create a ripple effect Wave.prototype.gradual = function (x, y, width, step) { (this.wave1).gradual(x, y, width, step)(); (this.wave2).gradual(x, y, width / 2, step)(); } //Clear this effect Wave.prototype.clear = function () { cancelAnimationFrame(this.wave1.requestID); cancelAnimationFrame(this.wave2.requestID); this.wave1.circle.setAttribute('cx', 0); this.wave1.circle.setAttribute('cy', 0); this.wave1.circle.setAttribute('r', 0); this.wave2.circle.setAttribute('cx', 0); this.wave2.circle.setAttribute('cy', 0); this.wave2.circle.setAttribute('r', 0); } //Text class function Text(x, y, size, color, family, value, href, target) { this.x = x; this.y = y; this.size = size, this.color = color, this.value = value; this.href = href; this.target = target; this.family = family; } Text.prototype.draw = function () { this.a = createSvgElement('a'); this.a.setAttribute('xlink:href', this.href); this.a.setAttribute('target', this.target); this.a.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.href); this.txt = createSvgElement('text'); this.txt.setAttribute('x', this.x); this.txt.setAttribute('y', this.y); this.txt.style.fill = this.color; this.txt.style.fontSize = this.size; this.txt.style.fontFamily = this.family; this.txt.style.cursor = 'pointer'; var valueNode = document.createTextNode(this.value); this.txt.appendChild(valueNode); this.a.appendChild(this.txt); svg.appendChild(this.a); } Text.prototype.changeOpacity = function (opacity) { this.txt.style.fill = this.color.slice(0, 17) + opacity + ')'; } //Line class function Line(begin, end, strokeWidth, color) { this.beginPoint = begin; this.endPoint = end; this.line = createSvgElement('line'); this.progress = 0 this.line.setAttribute('x1', this.beginPoint.x); this.line.setAttribute('y1', this.beginPoint.y); this.line.setAttribute('x2', this.beginPoint.x); this.line.setAttribute('y2', this.beginPoint.y); this.line.style.stroke = color; this.line.style.strokeWidth = strokeWidth; svg.appendChild(this.line); } //Create link effect Line.prototype.bulid = function (step) { var progress = 0; var tempCoordinate = { x: this.beginPoint.x, y: this.beginPoint.y } var speed = getSpeed(this.beginPoint, this.endPoint, step); //step by step to draw line, wave too. var drawRun = function () { progress++; this.line.setAttribute('x2', tempCoordinate.x); this.line.setAttribute('y2', tempCoordinate.y); tempCoordinate.x += speed.X; tempCoordinate.y += speed.Y; if (progress <= step) { this.requestID = requestAnimationFrame(drawRun); } }.bind(this); return drawRun; } //Clear this effect Line.prototype.clear = function () { //this.progress = 100000000; //setTimeout(function () { //}.bind(this), 17.7); cancelAnimationFrame(this.requestID); this.line.setAttribute('x2', this.beginPoint.x); this.line.setAttribute('y2', this.beginPoint.y); } //All Line function function drawAllLine(lines, needTime) { var timeStep = needTime / (1000 / 60); for (var j = 0; j < lines.length; j++) { lines[j].clear(); (lines[j].bulid(timeStep))(); } } function clearAllLine(lines) { for (var j = 0; j < lines.length; j++) { lines[j].clear(); } } //Create polygon area according to the point function createPolygon(pointArr) { var polygon = createSvgElement('polygon'); var notMainPointArr = pointArr.clone(); notMainPointArr.splice(0, 1); var pointStr = createPointStr(notMainPointArr); polygon.setAttribute('points', pointStr); polygon.style.fill = "rgba(255,255,255,0)"; svg.appendChild(polygon); return polygon; } //draw all points ,lines... function drawAll(pointArr, textArr, time) { var polygon = createPolygon(pointArr); var wave = new Wave(); var lines = []; var line1, line2; for (var i = 1; i < pointArr.length; i++) { var line1, line2; if (pointArr[i].isLink) { line1 = new Line(pointArr[i], pointArr[i + 1 == pointArr.length ? 1 : i + 1], 1, "rgba(255,255,255,0.4)"); } line2 = new Line(pointArr[0], pointArr[i], 1, "rgba(255,255,255,0.4)"); lines.push(line1); lines.push(line2); } for (var i = 0; i < pointArr.length; i++) { (function (i) { for (var j = 0; j < textArr[i].length; j++) { (function (j) { textArr[i][j].draw(); EventUtil.addHandler(textArr[i][j].a, 'mouseover', function () { if (i != 0) { textArr[i][j].changeOpacity(0.8); } drawAllLine(lines, time); }); EventUtil.addHandler(textArr[i][j].a, 'mouseout', function () { if (i != 0) { textArr[i][j].changeOpacity(0.4); } clearAllLine(lines); }); })(j) } pointArr[i].draw(); EventUtil.addHandler(pointArr[i].circle, 'mouseover', function () { wave.gradual(pointArr[i].x, pointArr[i].y, i == 0 ? pointArr[i].r * 10 : pointArr[i].r * 8, 70); changeAllColor(pointArr, 0.8); drawAllLine(lines, time); }); EventUtil.addHandler(pointArr[i].circle, 'mouseout', function () { wave.clear(); changeAllColor(pointArr, 0.4); clearAllLine(lines); }); })(i) } EventUtil.addHandler(polygon, 'mouseover', function () { drawAllLine(lines, time); changeAllColor(pointArr, 0.8); wave.gradual(pointArr[0].x, pointArr[0].y, pointArr[0].r * 10, 80); }); EventUtil.addHandler(polygon, 'mouseout', function () { clearAllLine(lines); changeAllColor(pointArr, 0.4); wave.clear(); }); } function configToObjectAndDraw(configObj) { var target = configObj.target; var fontFamily = configObj.fontFamily; var lineNeedTime = configObj.drawLineNeedTime; var points, texts; var mainContent, mainPoint, mainTexts; var otherContent, otherR, otherSize, otherTextColor, otherPointColor, otherPoints, otherTexts; for (var j = 0; j < configObj.polygonArray.length; j++) { points = []; texts = []; mainContent = configObj.polygonArray[j].mainContent; mainPoint = mainContent.point; mainTexts = mainContent.texts; var pointTextArr; points[0] = new Point(mainPoint.x, mainPoint.y, mainPoint.r, mainPoint.color); for (var o = 0; o < mainTexts.length; o++) { pointTextArr = []; pointTextArr[o] = new Text(mainPoint.x + mainTexts[o].offsetX, mainPoint.y + mainTexts[o].offsetY, mainTexts[o].fontSize, mainTexts[o].color, fontFamily, mainTexts[o].value, mainTexts[o].href, target); } texts.push(pointTextArr); otherContent = configObj.polygonArray[j].otherContent; otherR = otherContent.r; otherSize = otherContent.textFontSize; otherTextColor = otherContent.textColor; otherPointColor = otherContent.pointColor; otherPoints = otherContent.points; otherTexts = otherContent.texts; var point, text, pointTexts; for (var i = 0; i < otherPoints.length; i++) { if (isRelative) { point = new Point(otherPoints[i].x + mainPoint.x, otherPoints[i].y + mainPoint.y, otherR, otherPointColor, otherPoints[i].isLink); } else { point = new Point(otherPoints[i].x, otherPoints[i].y, otherR, otherPointColor, otherPoints[i].isLink); } pointTexts = otherTexts[i]; pointTextArr = []; for (var o = 0; o < pointTexts.length; o++) { if (isRelative) { text = new Text(mainPoint.x + otherPoints[i].x + pointTexts[o].offsetX, mainPoint.y + otherPoints[i].y + pointTexts[o].offsetY, otherSize, otherTextColor, fontFamily, pointTexts[o].value, pointTexts[o].href, target); } else { text = new Text(otherPoints[i].x + pointTexts[o].offsetX, otherPoints[i].y + pointTexts[o].offsetY, otherSize, otherTextColor, fontFamily, pointTexts[o].value, pointTexts[o].href, target); } pointTextArr.push(text); } points.push(point); texts.push(pointTextArr); } drawAll(points, texts, lineNeedTime); } } //Size response EventUtil.addHandler(window, 'resize', function () { svg.innerHTML = ''; recoverAllxy(configObj); HEIGHT = svg.clientHeight; WIDTH = svg.clientWidth; changeAllxy(configObj); configToObjectAndDraw(configObj); }); //public this.draw = function () { //execute changeAllxy(configObj); configToObjectAndDraw(configObj); } } </script> </head> <body> <svg id="svgByYozo" xmlns="http://www.w3.org/2000/svg" version="1.1"> </svg> <script> var configObj = { "fontFamily": "Microsoft YaHei", "target": "_blank", "drawLineNeedTime": 1000, "polygonArray": [{ "mainContent": { "point": { "x": 0.3245, "y": 0.5835, "r": 4.5, "color": "rgba(255,78,207,0.9)" }, "texts": [{ "offsetX": -65, "offsetY": 4.5, "fontSize": "13px", "color": "rgba(255,255,255,0.8)", "value": "金融服务", "href": "#" }] }, "otherContent": { "r": 3.5, "textFontSize": "10px", "pointColor": "rgba(255,255,255,0.4)", "textColor": "rgba(255,255,255,0.4)", "points": [ { "x": -0.1182, "y": -0.0128, "isLink": true }, { "x": -0.0727, "y": -0.0771, "isLink": false }, { "x": -0.0145, "y": 0.1029, "isLink": true }, { "x": -0.1, "y": 0.09, "isLink": true } ], "texts": [[{ "offsetX": -55, "offsetY": 3.5, "value": "理财业务", "href": "#" }], [{ "offsetX": -55, "offsetY": 4.5, "value": "百度钱包", "href": "#" }], [{ "offsetX": 10, "offsetY": 4.5, "value": "消费信贷", "href": "#" }], [{ "offsetX": -25, "offsetY": 20, "value": "金融风控", "href": "#" }]] } }, { "mainContent": { "point": { "x": 0.6845, "y": 0.3393, "r": 4.5, "color": "#ffde00" }, "texts": [{ "offsetX": -65, "offsetY": 4.5, "fontSize": "13px", "color": "rgba(255,255,255,0.8)", "value": "搜索公司", "href": "#" }] }, "otherContent": { "r": 3.5, "textFontSize": "10px", "pointColor": "rgba(255,255,255,0.4)", "textColor": "rgba(255,255,255,0.4)", "points": [ { "x": -0.0727, "y": -0.0385, "isLink": true }, { "x": -0.0181, "y": -0.0964, "isLink": true }, { "x": 0.0546, "y": -0.0642, "isLink": true }, { "x": 0.091, "y": -0.0128, "isLink": true }, { "x": -0.0181, "y": 0.0565, "isLink": false }, ], "texts": [[{ "offsetX": -55, "offsetY": 3.5, "value": "百度糯米", "href": "#" }], [{ "offsetX": 10, "offsetY": 4.5, "value": "大搜索", "href": "#" }, { "offsetX": 58, "offsetY": 4.5, "value": "凤巢", "href": "#" }], [{ "offsetX": 10, "offsetY": 4.5, "value": "百度地图", "href": "#" }], [{ "offsetX": 10, "offsetY": 4.5, "value": "个人云", "href": "#" }, { "offsetX": 58, "offsetY": 4.5, "value": "贴吧", "href": "#" }, { "offsetX": 94, "offsetY": 4.5, "value": "输入法", "href": "#" }, { "offsetX": 142, "offsetY": 4.5, "value": "浏览器", "href": "#" }], [{ "offsetX": 10, "offsetY": 4.5, "value": "知识搜素", "href": "#" }, { "offsetX": 70, "offsetY": 4.5, "value": "移动分发", "href": "#" }, { "offsetX": 130, "offsetY": 4.5, "value": "商业生态", "href": "#" }]] } }] } window.onload = function () { setTimeout(function () { var svg = document.getElementById('svgByYozo'); var radialByYozo = new RayMap(svg, configObj, true); radialByYozo.draw(); }, 100) } </script> </body> </html>