接着上一節的內容,本次學習主要介紹SVG組合式應用以及js交互式應用!
1、組合式應用
繪制兩棵帶有投影效果的樹!
<svg width="400" height="600"> <defs> <pattern id="grap" patternUnits="userSpaceOnUse" x="0" y="0" width="100" height="67" viewBox="0 0 102 76"> <image x="0" y="0" width="102" height="76" xlink:href="http://pic27.nipic.com/20130324/9148618_153134223000_2.jpg"></image> </pattern> <linearGradient id="TrunkGrad"> <stop offset="0%" stop-color="#663300"></stop> <stop offset="40%" stop-color="#996600"></stop> <stop offset="100%" stop-color="#552200"></stop> </linearGradient> <rect x="-5" y="-50" width="10" height="50" id="Trunk"></rect> <path d="M-25,-50L-10,-80L-20,-80L-5,-110L-15,-110L0,-140L15,-110L5,-110L20,-80L10,-80L25,-50Z" fill="#f00" id="can"> </path> <linearGradient id="shadow" x=0 y=0 x2=0 y2=100%> <stop offset="0%" stop-color="#000" stop-opacity=".5"></stop> <stop offset="20%" stop-color="#996600" stop-opacity="0"></stop> </linearGradient> <g id="tree"> <use xlink:href="#Trunk" fill="url(#TrunkGrad)"/> <use xlink:href="#Trunk" fill="url(#shadow)"/> <use xlink:href="#can" fill="none" stroke="#663300" stroke-linejoin="round" stroke-width="4px" /> <use xlink:href="#can" fill="#339900" stroke="none"/> </g> <g id="treeShadow"> <use xlink:href="#Trunk" fill="#000"/> <use xlink:href="#can" fill="#000" stroke="none"/> </g> </defs> <text y=60 x=200 font-family="Arial" font-size="60px" fill="#996600" text-anchor="middle">tree</text> <text y=90 x=200 font-family="Arial" font-size="20px" fill="#996600" text-anchor="middle" id="treeCounter"></text> <text y=550 x=20 font-family="Arial" font-size="20px" fill="#996600" text-anchor="left"> <tspan>點擊一顆樹或樹的影子</tspan> <tspan>並移除掉它。。。</tspan> </text> <g transform="translate(-10,350)" stroke-width="20" stroke="url(#grap)" stroke-linejoin="round"> <path d="M0,0Q170,-50 260,-190Q310,-250 410,-250" fill="none"> </path> </g> <!--skewX() x軸方向向右扭曲25像素--> <use xlink:href="#treeShadow" transform="translate(130,250) scale(1,.6) skewX(-25)" opacity="0.4" /> <use xlink:href="#tree" transform="translate(130,250)" /> <use xlink:href="#treeShadow" transform="translate(260,500) scale(2,1.2) skewX(-25)" opacity="0.4" /> <use xlink:href="#tree" transform="translate(260,500) scale(2)" /> </svg>
說明:
scale(1,.6) :縮放 x軸縮放1倍,y軸縮放0.6倍
skewX(-25) :扭曲 x軸水平方向扭曲-25像素
<text y=550 x=20 font-family="Arial" font-size="20px" fill="#996600" text-anchor="left"> <tspan>點擊一顆樹或樹的影子</tspan> <tspan>並移除掉它。。。</tspan> </text>
這里的tspan 類似於我們在頁面中添加span標簽,用於分割漢字
<linearGradient id="shadow" x=0 y=0 x2=0 y2=100%> <stop offset="0%" stop-color="#000" stop-opacity=".5"></stop> <stop offset="20%" stop-color="#996600" stop-opacity="0"></stop> </linearGradient>
stop-opacity=".5" :漸變的透明度設置
上訴代碼運行結果如圖:
2、SVG交互式應用
我們希望自己可以點擊按鈕的時候生成一顆隨機的樹,位置控制在svg畫板中,而且點擊生成的樹還可以移除掉它!
新樹的尺寸控制在50% - 150% 之間進行隨機縮放!
首先我們創建一個添加樹的函數:
/* document.createElementNS() 創建帶有命名空間的的<use>元素 setAttributeNS() 方法創建或改變具有命名空間的屬性。 語法: elementNode.setAttributeNS(name,value) */ document.getElementById('btn').onclick = function(){ var x = Math.floor(Math.random()*400);//隨機數x var y = Math.floor(Math.random()*600);//隨機數y var scale = Math.random()+0.5;//生成隨機縮放的比例 var translate = 'translate('+x+','+y+')'; var tree = document.createElementNS('http://www.w3.org/2000/svg','use'); var treeSd = document.createElementNS('http://www.w3.org/2000/svg','use'); treeSd.setAttributeNS('http://www.w3.org/1999/xlink','xlink:href','#treeShadow'); treeSd.setAttribute('transform',translate + ' scale('+ scale +','+ scale*0.6 +') skewX(-25)'); treeSd.setAttribute('opacity',0.4); document.querySelector('svg').appendChild(treeSd);//添加到svg中 tree.setAttributeNS('http://www.w3.org/1999/xlink','xlink:href','#tree'); tree.setAttribute('transform',translate + ' scale('+ scale +')'); document.querySelector('svg').appendChild(tree);//添加到svg中 updateTrees(); }
接着我們創建一個更新樹的數量的函數,以及給每棵樹添加自己的移除的方法
function updateTrees(){ //查找所有的use元素 var list = document.querySelectorAll('use'); var treeCount = 0; for(var i=0;i<list.length;i++){ //如果是樹或者樹的陰影 if(list[i].getAttribute('xlink:href') == '#tree' || list[i].getAttribute('xlink:href') == '#treeShadow'){ treeCount++; //點擊樹或者陰影移除自己 list[i].onclick = removeTree; } } //更新數量 var counter = document.getElementById('treeCon'); counter.innerHTML = parseInt(treeCount/2) + 'trees in the svg'; }
創建樹的移除的函數
function removeTree(e){ //e.target 被點擊的目標對象 var e = e.target; /* e.correspondingUserElement 意思大概是當使用的元素有嵌套的時候使用最外層的元素作為目標對象 具體說明可參考地址: https://msdn.microsoft.com/en-us/library/ff971929(v=vs.85).aspx */ if(e.correspondingUserElement){ e = e.correspondingUserElement; } e.parentNode.removeChild(e); updateTrees(); }
完整的例子如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>svg 交互測試</title> </head> <style> svg{border:1px solid #000;} use:nth-of-type(even):hover{ opacity:0.9; cursor:crosshair;/*十字線光標*/ } use:nth-of-type(odd):hover{ opacity:0.5; cursor:crosshair;/*十字線光標*/ } </style> <body> <div > <button type="button" id="btn">點擊按鈕生成樹</button> </div> <svg width="400" height="600"> <defs> <pattern id="grap" patternUnits="userSpaceOnUse" x="0" y="0" width="100" height="67" viewBox="0 0 102 76"> <image x="0" y="0" width="102" height="76" xlink:href="http://pic27.nipic.com/20130324/9148618_153134223000_2.jpg"></image> </pattern> <linearGradient id="TrunkGrad"> <stop offset="0%" stop-color="#663300"></stop> <stop offset="40%" stop-color="#996600"></stop> <stop offset="100%" stop-color="#552200"></stop> </linearGradient> <rect x="-5" y="-50" width="10" height="50" id="Trunk"></rect> <path d="M-25,-50L-10,-80L-20,-80L-5,-110L-15,-110L0,-140L15,-110L5,-110L20,-80L10,-80L25,-50Z" fill="#f00" id="can"> </path> <linearGradient id="shadow" x=0 y=0 x2=0 y2=100%> <stop offset="0%" stop-color="#000" stop-opacity=".5"></stop> <stop offset="20%" stop-color="#996600" stop-opacity="0"></stop> </linearGradient> <g id="tree"> <use xlink:href="#Trunk" fill="url(#TrunkGrad)"/> <use xlink:href="#Trunk" fill="url(#shadow)"/> <use xlink:href="#can" fill="none" stroke="#663300" stroke-linejoin="round" stroke-width="4px" /> <use xlink:href="#can" fill="#339900" stroke="none"/> </g> <g id="treeShadow"> <use xlink:href="#Trunk" fill="#000"/> <use xlink:href="#can" fill="#000" stroke="none"/> </g> </defs> <text y=60 x=200 font-family="Arial" font-size="60px" fill="#996600" text-anchor="middle">tree</text> <text y=90 x=200 font-family="Arial" font-size="20px" fill="#996600" text-anchor="middle" id="treeCounter"></text> <text y=550 x=20 font-family="Arial" font-size="20px" fill="#996600" text-anchor="left"> <tspan>點擊一顆樹或樹的影子</tspan> <tspan>並移除掉它。。。</tspan> </text> <g transform="translate(-10,350)" stroke-width="20" stroke="url(#grap)" stroke-linejoin="round"> <path d="M0,0Q170,-50 260,-190Q310,-250 410,-250" fill="none"> </path> </g> <!--skewX() x軸方向向右扭曲25像素--> <use xlink:href="#treeShadow" transform="translate(130,250) scale(1,.6) skewX(-25)" opacity="0.4" /> <use xlink:href="#tree" transform="translate(130,250)" /> <use xlink:href="#treeShadow" transform="translate(260,500) scale(2,1.2) skewX(-25)" opacity="0.4" /> <use xlink:href="#tree" transform="translate(260,500) scale(2)" /> </svg> <p id="treeCon"></p> </body> <script> /* document.createElementNS() 創建帶有命名空間的的<use>元素 setAttributeNS() 方法創建或改變具有命名空間的屬性。 語法: elementNode.setAttributeNS(name,value) */ document.getElementById('btn').onclick = function(){ var x = Math.floor(Math.random()*400);//隨機數x var y = Math.floor(Math.random()*600);//隨機數y var scale = Math.random()+0.5;//生成隨機縮放的比例 var translate = 'translate('+x+','+y+')'; var tree = document.createElementNS('http://www.w3.org/2000/svg','use'); var treeSd = document.createElementNS('http://www.w3.org/2000/svg','use'); treeSd.setAttributeNS('http://www.w3.org/1999/xlink','xlink:href','#treeShadow'); treeSd.setAttribute('transform',translate + ' scale('+ scale +','+ scale*0.6 +') skewX(-25)'); treeSd.setAttribute('opacity',0.4); document.querySelector('svg').appendChild(treeSd);//添加到svg中 tree.setAttributeNS('http://www.w3.org/1999/xlink','xlink:href','#tree'); tree.setAttribute('transform',translate + ' scale('+ scale +')'); document.querySelector('svg').appendChild(tree);//添加到svg中 updateTrees(); } function updateTrees(){ //查找所有的use元素 var list = document.querySelectorAll('use'); var treeCount = 0; for(var i=0;i<list.length;i++){ //如果是樹或者樹的陰影 if(list[i].getAttribute('xlink:href') == '#tree' || list[i].getAttribute('xlink:href') == '#treeShadow'){ treeCount++; //點擊樹或者陰影移除自己 list[i].onclick = removeTree; } } //更新數量 var counter = document.getElementById('treeCon'); counter.innerHTML = parseInt(treeCount/2) + 'trees in the svg'; } function removeTree(e){ //e.target 被點擊的目標對象 var e = e.target; /* e.correspondingUserElement 意思大概是當使用的元素有嵌套的時候使用最外層的元素作為目標對象 具體說明可參考地址: https://msdn.microsoft.com/en-us/library/ff971929(v=vs.85).aspx */ if(e.correspondingUserElement){ e = e.correspondingUserElement; } e.parentNode.removeChild(e); updateTrees(); } </script>
說明:
use:nth-of-type(even):hover{ opacity:0.9; cursor:crosshair;/*十字線光標*/ } use:nth-of-type(odd):hover{ opacity:0.5; cursor:crosshair;/*十字線光標*/ }
這里是css3 新的選擇方法
use:nth-of-type(even):選擇奇數的use元素
use:nth-of-type(odd):選擇偶數的use元素
當點擊按鈕的時候可以生成同樣帶有的投影效果的樹,位置不一,大小不一!
鼠標移動到樹或者影子的上面的時候出現十字光標,點擊可以移除樹或者影子
例子中我們看到,svg是可以通過dom操作元素,並添加事件處理函數的!這點比canvas在事件處理方面更靈活!
SVG的介紹大概先介紹這些,具體詳細的API可以參考下面的地址:
https://developer.mozilla.org/zh-CN/docs/Web/SVG