SVG 可以很不錯的和 CSS 整合在一起,那麼來看看和 javascript 相關的 API
動畫控制
SVG 的動畫控制上,針對單一動畫很奇怪的沒有 暫停 這個功能,只能對全部的 SVG 動畫全部暫停
指令 :
svg.pauseAnimations();
svg.unpauseAnimations();
範例如下:
<svg id="a120700_svg" width="300" height="60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="10" y="10" width="20" height="20">
<animate attributeName="x" values="10;200" dur="3s" repeatCount="indefinite"></animate>
</rect>
</svg><br>
<button id="a120700_pause">暫停</button>
<button id="a120700_unpause">繼續</button>
<br>
<script>
$(()=>
{
$("#a120700_pause").on("click",()=>
{
$("#a120700_svg")[0].pauseAnimations();
});
$("#a120700_unpause").on("click",()=>
{
$("#a120700_svg")[0].unpauseAnimations();
});
});
</script>
對於單一動畫比較會用到的 API 有這些
getCurrentTime() - 取得目前動畫的時間
beginElement() - 開始動畫
beginElementAt(時間) - 在時間(秒)後開始動畫
endElement() - 停止動畫
endElementAt(時間) - 在時間(秒)後停止動畫
EVENT 的部份有這三個
beginEvent - 動畫開始時
endEvent - 動畫停止時
repeatEvent - 動畫重覆時
先來一個簡單的範例,範例中每 100ms 更新一次狀態,用下面這段程式碼來取得動畫執行中的 x 座標,如果要設定計 暫停 的功能,必須先取得座標,在下次執行時從這裡開始,然而這個解法有很多問題,最理想的還是等 SVG 的動畫新增暫停的指令
document.getElementById("a120701_r1").x.animVal.value;
<svg width="300" height="60">
<rect id="a120701_r1" x="10" y="10" width="30" height="30">
<animate id="a120701_a1" attributeName="x" to="250" dur="6s" repeatCount="indefinite" begin="indefinite" end="indefinite" fill="freeze"></animate>
</rect>
</svg> <br>
<button id="a120701_start">點我開始</button>
<button id="a120701_stop">點我停止</button>
<br><br>
動畫時間 : <span id="a120701_time"></span><br>
x 座標 : <span id="a120701_xloc"></span><br><br>
<textarea id="a120701_status" style="width:300px;height:100px"></textarea>
<script>
$(()=>
{
let hh="";
let tt=0;
let a1=document.getElementById("a120701_a1");
/////////
a1.addEventListener("beginEvent",function()
{
show("beginEvent");
});
a1.onbegin=function()//這個用法只有 chrome 有用
{
show("onbegin");
}
/////////
a1.addEventListener("endEvent",function()
{
show("endEvent");
});
a1.onend=function()//這個用法只有 chrome 有用
{
show("onend");
}
///////// safari 和 iphone 不支援 repeat
a1.addEventListener("repeatEvent",function()
{
show("repeatEvent");
});
a1.onrepeat=function()//這個用法只有 chrome 有用
{
show("onrepeat");
}
$("#a120701_start").on("click",function()
{
a1.beginElement();
});
$("#a120701_stop").on("click",function()
{
a1.endElement();
});
function show(msg)
{
tt=a1.getCurrentTime().toFixed(2);
hh=tt+":"+msg+"\n"+hh;
$("#a120701_status").html(hh);
}
function update()
{
if (!a1) return;
tt=a1.getCurrentTime().toFixed(2);
$("#a120701_time").html(tt);
let r1=document.getElementById("a120701_r1");
let ax=r1.x.animVal.value.toFixed(2);
$("#a120701_xloc").html(ax);
setTimeout(update,100);
}
update();
})
</script>
動畫時間 : 0.03
x 座標 : 10.00
既然可以用 javascript 控制,那麼先來修改一下上一篇的時鐘,來把時間調成目前時間
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" stroke="#000">
<circle id="a120702_o1" cx="150" cy="150" r="140" fill="none" stroke="#000" stroke-width="2"></circle>
<g id="a120702_g3">
<g id="a120702_g2">
<g id="a120702_g1" stroke="#00f">
<line x1="10" y1="150" x2="40" y2="150" stroke-width="3"></line>
<defs>
<line id="a120702_d1" x1="10" y1="150" x2="20" y2="150" stroke="#f00"></line>
</defs>
<use xlink:href="#a120702_d1" transform="rotate(6,150,150)"></use>
<use xlink:href="#a120702_d1" transform="rotate(12,150,150)"></use>
<use xlink:href="#a120702_d1" transform="rotate(18,150,150)"></use>
<use xlink:href="#a120702_d1" transform="rotate(24,150,150)"></use>
</g>
<use xlink:href="#a120702_g1" transform="rotate(30,150,150)"></use>
<use xlink:href="#a120702_g1" transform="rotate(60,150,150)"></use>
</g>
<use xlink:href="#a120702_g2" transform="rotate(90,150,150)"></use>
</g>
<use xlink:href="#a120702_g3" transform="rotate(180,150,150)"></use>
<line id="a120702_hh" x1="150" y1="150" x2="150" y2="80" stroke-width="10">
<animateTransform attributeName="transform" type="rotate" values="0,150,150;360,150,150" dur="43200s" repeatCount="indefinite"></animateTransform>
</line>
<line id="a120702_mm" x1="150" y1="150" x2="150" y2="50" stroke-width="6">
<animateTransform attributeName="transform" type="rotate" values="0,150,150;360,150,150" dur="3600s" repeatCount="indefinite"></animateTransform>
</line>
<line id="a120702_ss" x1="150" y1="150" x2="150" y2="30" stroke-width="2" stroke="#f00">
<animateTransform attributeName="transform" type="rotate" values="0,150,150;360,150,150" dur="60s" repeatCount="indefinite"></animateTransform>
</line>
<circle id="o2" cx="150" cy="150" r="8"></circle>
</svg>
<script>
$(()=>
{
let tt=new Date();
let hh=tt.getHours();
let mm=tt.getMinutes();
let ss=tt.getSeconds();
//
if (hh>12) hh-=12;
//
let ahh=$("#a120702_hh > animateTransform");
let amm=$("#a120702_mm > animateTransform");
let ass=$("#a120702_ss > animateTransform");
//
let dh=360*(hh+(mm/60)+(ss/3600))/12;
ahh.attr("values",dh+",150,150;"+(dh+360)+",150,150");
//
let dm=360*(mm+ss/60)/60;
amm.attr("values",dm+",150,150;"+(dm+360)+",150,150");
//
let ds=360*ss/60;
ass.attr("values",ds+",150,150;"+(ds+360)+",150,150");
//
});
</script>
新增物件
SVG 由於命名空間的問題,用 html 的 append 新增html字串時不會有反應, 之前用過一個技巧,就是重寫裡頭的 html 來產生效果,其實更正確的方式是,建立一個屬於 svg 命名空間的物件,就可以用 append 加入了,方法如下:
var obj=document.createElementNS('http://www.w3.org/2000/svg', "tag 名稱,例如 rect");
建立 obj 後可以用
obj.setAttribute("參數",值);
或用 jquery
$(obj).attr("參數",值);
範例如下:
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">
<g id="a120703_g1">
<rect id="a120703_r1" x="10" y="10" width="30" height="30" stroke="#f00" fill="#ff0"></rect>
</g>
</svg><br>
<button id="a120703_b1">用append新增</button>
<button id="a120703_b2">重新寫入html</button>
<button id="a120703_b3">用createElementNS新增</button>
<br>
<script>
$(()=>
{
let yloc=50;
$("#a120703_b1").on("click",()=>
{
let i;
let hh="";
for (i=0;i<3;i++)
{
hh+='<rect id="a120703_h'+(yloc+i)+'" x="'+(10+i*40)+'" y="'+yloc+'" width="30" height="30" stroke="#00f" fill="#0ff"></rect>';
}
$("#a120703_g1").append(hh);//append 後,原始碼有新增,但是沒效果
yloc+=40;
});
$("#a120703_b2").on("click",()=>
{
$("#a120703_g1").html($("#a120703_g1").html());//重寫整個 html 後才有效
});
$("#a120703_b3").on("click",()=>
{
let i;
let hh="";
for (i=0;i<3;i++)
{
let o=document.createElementNS('http://www.w3.org/2000/svg', "rect");//建立一個 svg 命名空間的物件
let id="a120703_h"+(yloc+i);
o.setAttribute("id", id);//設定該物件的 ID
$("#a120703_g1").append(o);//把物件 append 上去,因為是同一個命名空間,會立刻出現
$("#"+id).attr("x",(10+i*40));//已經 append 後,可以用 jquery 操作
$(o).attr("y",yloc);//也可以直接用物件的方式修改屬性
$(o).attr("width",30);
$(o).attr("height",30);
$(o).attr("stroke","#00f");
$(o).attr("fill","#a0f");
}
yloc+=40;
});
});
</script>
沒有留言:
張貼留言