タイトルどおりですが、矢印をSVGで描画するための関数をつくってみましたので、紹介しておきます。
function CreateVector(index,cx,cy,Len,Wid,Ang,Ra,AngRot,FilColor){
vectors[index] = document.createElementNS('http://www.w3.org/2000/svg', 'path');
let p1x = cx;
let p1y = cy;
let p2x = cx;
let p2y = cy - 0.5*Wid;
let p3x = Len - Ra*Math.cos(0.5*Ang*Math.PI/180)+cx;
let p3y = p2y;
let p4x = p3x;
let p4y = cy - Ra*Math.sin(0.5*Ang*Math.PI/180);
let p5x = cx + Len;
let p5y = cy;
let p6x = p3x;
let p6y = cy + Ra*Math.sin(0.5*Ang*Math.PI/180);
let p7x = p3x;
let p7y = cy + 0.5*Wid;
let p8x = cx;
let p8y = p7y;
let temp ="M"+ p1x+","+p1y+" L"+p2x+","+p2y+" L"+p3x+","+p3y+" L"+p4x+","+p4y+" L"+p5x+","+p5y+" L"+p6x+","+p6y+" L"+p7x+","+p7y+" L"+p8x+","+p8y+" Z";
vectors[index].setAttribute('d',temp);
temp="rotate("+ AngRot +" "+cx+" "+cy+")";
vectors[index].setAttribute('transform',temp);
vectors[index].setAttribute('fill',FilColor);
vector_svg.appendChild(vectors[index]);
}
関数の入力パラメータは下図のように定義してます。矢印をたくさん追加できるようにSVGのpath要素の配列vectorsを定義してます。
実際に矢印を書いてみます。
<html lang="ja">
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<script type="text/javascript"></script>
</head>
<body>
<div id="svg_container" class="svg-over-div" >
</div>
<script>
let width =200;
let height = 200;
let cx =50;
let cy =100;
let Len =50;
let Wid = 10;
let Ang =90;
let FilColor = '#dc143c';
let Ra = Wid*1.5;
const vector_svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
const vectors = [];
function CreateVector(index,cx,cy,Len,Wid,Ang,Ra,AngRot,FilColor){
vectors[index] = document.createElementNS('http://www.w3.org/2000/svg', 'path');
let p1x = cx;
let p1y = cy;
let p2x = cx;
let p2y = cy - 0.5*Wid;
let p3x = Len - Ra*Math.cos(0.5*Ang*Math.PI/180)+cx;
let p3y = p2y;
let p4x = p3x;
let p4y = cy - Ra*Math.sin(0.5*Ang*Math.PI/180);
let p5x = cx + Len;
let p5y = cy;
let p6x = p3x;
let p6y = cy + Ra*Math.sin(0.5*Ang*Math.PI/180);
let p7x = p3x;
let p7y = cy + 0.5*Wid;
let p8x = cx;
let p8y = p7y;
let temp ="M"+ p1x+","+p1y+" L"+p2x+","+p2y+" L"+p3x+","+p3y+" L"+p4x+","+p4y+" L"+p5x+","+p5y+" L"+p6x+","+p6y+" L"+p7x+","+p7y+" L"+p8x+","+p8y+" Z";
vectors[index].setAttribute('d',temp);
temp="rotate("+ AngRot +" "+cx+" "+cy+")";
vectors[index].setAttribute('transform',temp);
vectors[index].setAttribute('fill',FilColor);
vector_svg.appendChild(vectors[index]);
}
window.onload = function() {
vector_svg.setAttribute("width", width);
vector_svg.setAttribute("height", height);
vector_svg.setAttribute('id',"inline_svg");
let index =0
let AngRot = 0;
CreateVector(index,cx,cy,Len,Wid,Ang,Ra,AngRot,FilColor);
document.querySelector('#svg_container').appendChild(vector_svg);
}
</script>
</body>
</html>
下が結果。RotAngをかえると、矢印が回転します。
矢印をたくさん描画する
let index =0
let AngRot = 0;
let num =10
for (let i=0;i<num;i++){
CreateVector(index,cx,cy,Len,Wid,Ang,Ra,AngRot,FilColor);
index++;
AngRot = 360/num * (i+1);
}
矢印の向きを可変する
マウスポインタの位置に矢印が向くようにしてみました。onmousemoveイベントを利用して、矢印原点(cx, cy)とポインタの位置から、角度を計算して、矢印を回転させます。
<html lang="ja">
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<script type="text/javascript"></script>
</head>
<body>
<div id="svg_container" class="svg-over-div" onmousemove="move()">
</div>
<script>
let width =200;
let height = 200;
let cx =[];
let cy =[];
let Len =20;
let Wid = 2;
let Ang =90;
let FilColor = '#dc143c';
let Ra = Wid*1.5;
const vector_svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
const vectors = [];
function move(){
demo_run=0;
var r = vector_svg.getBoundingClientRect();
var x=Math.round(event.clientX-r.left);
var y=Math.round(event.clientY-r.top);
for(let i=0;i<vectors.length;i++){
let xx = x-cx[i];
let yy = cy[i]-y;
let ang = Math.atan2(xx,yy)*180/(Math.PI)-90;
let temp="rotate("+ ang +" "+cx[i]+" "+cy[i]+")";
vectors[i].setAttribute('transform',temp);
}
}
window.onload = function() {
vector_svg.setAttribute("width", width);
vector_svg.setAttribute("height", height);
vector_svg.setAttribute('id',"inline_svg");
let index =0
for (let i =0;i<10;i++){
for (let j=0;j<10;j++){
cx[index]=i*10+50;
cy[index]=j*10+100;
CreateVector(index,cx[index],cy[index],Len,Wid,Ang,Ra,0,FilColor);
index++
}
}
document.querySelector('#svg_container').appendChild(vector_svg);
}
function CreateVector(index,cx,cy,Len,Wid,Ang,Ra,AngRot,FilColor){
vectors[index] = document.createElementNS('http://www.w3.org/2000/svg', 'path');
let p1x = cx;
let p1y = cy;
let p2x = cx;
let p2y = cy - 0.5*Wid;
let p3x = Len - Ra*Math.cos(0.5*Ang*Math.PI/180)+cx;
let p3y = p2y;
let p4x = p3x;
let p4y = cy - Ra*Math.sin(0.5*Ang*Math.PI/180);
let p5x = cx + Len;
let p5y = cy;
let p6x = p3x;
let p6y = cy + Ra*Math.sin(0.5*Ang*Math.PI/180);
let p7x = p3x;
let p7y = cy + 0.5*Wid;
let p8x = cx;
let p8y = p7y;
let temp ="M"+ p1x+","+p1y+" L"+p2x+","+p2y+" L"+p3x+","+p3y+" L"+p4x+","+p4y+" L"+p5x+","+p5y+" L"+p6x+","+p6y+" L"+p7x+","+p7y+" L"+p8x+","+p8y+" Z";
vectors[index].setAttribute('d',temp);
temp="rotate("+ AngRot +" "+cx+" "+cy+")";
vectors[index].setAttribute('transform',temp);
vectors[index].setAttribute('fill',FilColor);
vector_svg.appendChild(vectors[index]);
}
</script>
</body>
</html>
矢印の色にグラデーションをつける
マウスポインタの位置が矢印近づけば、赤色、遠ざかれば、青色になるようにしました。CreateColorGradationという関数を追加して、ポインタと矢印の距離からカラーコードを計算します。
<html lang="ja">
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<script type="text/javascript"></script>
</head>
<body>
<div id="svg_container" class="svg-over-div" onmousemove="move()">
</div>
<script>
let width =1000;
let height = 1000;
let cx =[];
let cy =[];
let Len =50;
let Wid = 5;
let Ang =90;
let FilColor = '#dc143c';
let Ra = Wid*1.5;
const vector_svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
const vectors = [];
function move(){
demo_run=0;
var r = vector_svg.getBoundingClientRect();
var x=Math.round(event.clientX-r.left);
var y=Math.round(event.clientY-r.top);
for(let i=0;i<vectors.length;i++){
let xx = x-cx[i];
let yy = cy[i]-y;
let rlen = Math.sqrt(xx**2+yy**2);
let ang = Math.atan2(xx,yy)*180/(Math.PI)-90;
let temp="rotate("+ ang +" "+cx[i]+" "+cy[i]+")";
vectors[i].setAttribute('transform',temp);
vectors[i].setAttribute('fill',CreateColorGradation(rlen));
}
}
window.onload = function() {
vector_svg.setAttribute("width", width);
vector_svg.setAttribute("height", height);
vector_svg.setAttribute('id',"inline_svg");
let index =0
for (let i =0;i<10;i++){
for (let j=0;j<10;j++){
cx[index]=i*50+50;
cy[index]=j*50+100;
CreateVector(index,cx[index],cy[index],Len,Wid,Ang,Ra,0,FilColor);
index++
}
}
document.querySelector('#svg_container').appendChild(vector_svg);
}
function CreateVector(index,cx,cy,Len,Wid,Ang,Ra,AngRot,FilColor){
vectors[index] = document.createElementNS('http://www.w3.org/2000/svg', 'path');
let p1x = cx;
let p1y = cy;
let p2x = cx;
let p2y = cy - 0.5*Wid;
let p3x = Len - Ra*Math.cos(0.5*Ang*Math.PI/180)+cx;
let p3y = p2y;
let p4x = p3x;
let p4y = cy - Ra*Math.sin(0.5*Ang*Math.PI/180);
let p5x = cx + Len;
let p5y = cy;
let p6x = p3x;
let p6y = cy + Ra*Math.sin(0.5*Ang*Math.PI/180);
let p7x = p3x;
let p7y = cy + 0.5*Wid;
let p8x = cx;
let p8y = p7y;
let temp ="M"+ p1x+","+p1y+" L"+p2x+","+p2y+" L"+p3x+","+p3y+" L"+p4x+","+p4y+" L"+p5x+","+p5y+" L"+p6x+","+p6y+" L"+p7x+","+p7y+" L"+p8x+","+p8y+" Z";
vectors[index].setAttribute('d',temp);
temp="rotate("+ AngRot +" "+cx+" "+cy+")";
vectors[index].setAttribute('transform',temp);
vectors[index].setAttribute('fill',FilColor);
vector_svg.appendChild(vectors[index]);
}
function (input){
let r= input/500;
if(r>1) r=1;
let color_code,temp1,temp2
temp1=Math.floor(255 - (255 - 5) * r);
temp2=Math.floor(22 + (255-22) * r);
let str1=('00'+temp1.toString(16)).slice(-2);
let str2=('00'+temp2.toString(16)).slice(-2);
let str3 = '01';
color_code = "#"+str1+str2+str2;
return color_code;
}
</script>
</body>
</html>