SVGアニメーション – javascriptを使う(3) – stroke要素の動的変化

Posted コメントするカテゴリー: javascript

SVGアニメーション – javascriptを使う(3) – stroke要素の動的変化

アニメーションとして取り扱えるSVGのプロパティの stroke を試してみます。
下記のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
#recttest {
    stroke-width: 10;
}
</style>

</head>
<body>

<svg xmlns="http://www.w3.org/2000/svg"
    width   = "500"
    height  = "250"
    viewBox = "0 0 500 250"
>
    <rect
        id     ="recttest"
        x      ="10"
        y      ="10"
        width  ="100"
        height ="100"
        fill   ="#ffffff"
    />
</svg>

<script>

    let color_value = 0;
    let millisecond = 50;
    let dom_rect    = document.querySelector("#recttest");

    setInterval(() => {

        let r = Math.round(color_value);
        let g = Math.round(color_value);
        let b = Math.round(color_value);

        if (r > 256) {
            color_value = 0;
        }
        color_value += 5;

        dom_rect.setAttribute('stroke', "rgb(" + r + "," + g + "," + b + ")");


    }, millisecond)

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、SVGのrect要素が出力されます。

javascriptによるstroke要素の動的変更で、rectの枠線の色要素(RGBの全要素)が「0→255」までの値で動的に変化します。

SVGアニメーション – javascriptを使う(2) – fill要素の動的変化

Posted コメントするカテゴリー: javascript

SVGアニメーション – javascriptを使う(2) – fill要素の動的変化

SVG要素をjavascriptを使ってアニメーションする方法を試します。

前回の投稿で、アニメーションとして取り扱えるSVGのプロパティを列挙しましたが、
その中から fill を試してみます。

下記のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.line {
    stroke-width: 5;
    stroke: #DEDEDE;
}
</style>

</head>
<body>

<svg xmlns="http://www.w3.org/2000/svg"
    width   = "500"
    height  = "250"
    viewBox = "0 0 500 250"
    style   = "background-color:#fff"
>
    <rect id="recttest" x="10" y="10" width="100" height="100" fill="#000000" />
</svg>

<script>

    let color_value = 0;
    let millisecond = 50;
    let dom_rect    = document.querySelector("#recttest");

    setInterval(() => {

        let r = Math.round(color_value);
        let g = Math.round(color_value);
        let b = Math.round(color_value);

        if (r > 255) {
            color_value = 0;
        }
        color_value += 5;

        let fill_color = "rgb(" + r + "," + g + "," + b + ")";
        dom_rect.setAttribute('fill', fill_color);


    }, millisecond)

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると開始座標(10,10)、終了座標(100,100)で、SVGのrect要素が出力されます。

また、javascriptによるfill要素の動的変更で、そのrectの色要素(RGBの全要素)が「0→255」までの値で動的に変化します。

millisecond は単純にミリ秒での変化なので、この場合は50ミリ秒でRGBの値を決定しているので、0.05秒の速さで「黒→白」まで変化することがわかります。

SVGアニメーション – javascriptを使う

Posted コメントするカテゴリー: javascript

SVGアニメーション – javascriptを使う

SVG要素をjavascriptを使ってアニメーションする方法を試します。

シンプルな line要素 を javascript制御で rotate属性を変化させて回転する例です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.line {
    stroke-width: 5;
    stroke: #DEDEDE;
}
</style>

</head>
<body>

<svg xmlns="http://www.w3.org/2000/svg"
    width   = "500"
    height  = "250"
    viewBox = "0 0 500 250"
    style   = "background-color:#fff"
>
    <line
        x1    = "0"
        y1    = "0"
        x2    = "80"
        y2    = "80"
        class = "line"
        id    = "linetest"
    />
</svg>

<script>

    let rotate_value = 0;
    let millisecond  = 50;
    let dom_line     = document.querySelector("#linetest");

    setInterval(() => {

        rotate_value += 3;

        dom_line.setAttribute('transform', 'translate(250, 125) rotate(' + rotate_value + ')');

    }, millisecond)

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると長さが80ピクセルのline(直線)を、javascript の setIntervalメソッド を使い、
50ミリ秒間隔で、動的に rotate(回転) しています。

また、アニメーションとして取り扱えるSVGのプロパティは、次のようなものがあります。

fill             : 要素の塗りつぶし色を指定
stroke           : 要素の境界線の色を指定
stroke-width     : 境界線の太さを指定
stroke-dasharray : 境界線の破線パターンを指定
fill-opacity     : 要素の透明度を指定
transform        : 要素の位置、回転、スケールなどの変換を指定
clip-path        : 要素の表示範囲をクリップするためのパスを指定
filter           : 要素に対して画像処理のフィルターを適用
text-anchor      : テキスト要素の配置基準点を指定
font-family      : テキストのフォントファミリーを指定
font-size        : テキストのフォントサイズを指定
text-decoration  : テキストの装飾(下線、取り消し線など)を指定
text-align       : テキストの水平方向の配置を指定します

プロパティごとのアニメーションの仕方はjavascriptの書き方が変わるので、
今後、別な投稿で触れる機会があるかと思います。

SVGアニメーション – CSS要素を使う(2) – transitionsプロパティの使用

Posted コメントするカテゴリー: javascript

SVGアニメーション – CSS要素を使う(2) – transitionsプロパティの使用

前回の投稿ではCSS要素の「animation」プロパティを使ってSVG画像をアニメーションしました。

今回は別なプロパティの「transitions」プロパティを使ってみます。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.anim1 {
    stroke: #000000;
    stroke-dasharray: 2000;
    stroke-dashoffset: 0;
    stroke-width: 10;
    transition: fill, 0s, 2s;
}

.anim1:hover {
    stroke: #ff00cc;
    stroke-dasharray: 500;
    stroke-width: 10;
}
</style>

</head>
<body>
 
<svg width="500" height="300" viewBox="0 0 500 300">
    <polygon
        class="anim1"
        points="10 15 25 120 50 180 75 95 98 250 105 140 130 175 135 210 150 135"
        stroke="#000000"
        stroke-width="1"
        fill="none"
    />
</svg>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると多角形が表示されます。

多角形(polygon)の線分にマウスカーソルを乗せると、下記のhover定義されたstyleにpolygonがアニメーション変化します。

.anim1:hover {
    stroke: #ff00cc;
    stroke-dasharray: 500;
    stroke-width: 10;
}

また、アニメーション変化の時間指定は

.anim1 {
    stroke: #000000;
    stroke-dasharray: 2000;
    stroke-dashoffset: 0;
    stroke-width: 10;
    transition: fill, 0s, 2s;
}

側にある

transition: fill, 0s, 2s;

で指定しています。

表示例(多角形上にマウスカーソルを乗せた場合)

本来は線分にマウスカーソルを乗せる方法ではなく、カーソルを乗せる領域を工夫してカーソルで選択しやすくします。

SVGアニメーション – CSS要素を使う

Posted コメントするカテゴリー: javascript

SVGアニメーション – CSS要素を使う

CSSアニメーション要素を使ってSVG画像をアニメーションさせます。

まずは、元となるSVG画像を表示するのみのサンプルです。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

</head>
<body>
 
<svg width="500" height="300" viewBox="0 0 500 300">
    <polygon
        class="anim1"
        points="10 15 25 120 50 180 75 95 98 250 105 140 130 175 135 210 150 135"
        stroke="#000000"
        stroke-width="1"
        fill="none"
    />
</svg>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると多角形が表示されます。

この多角形に、classを指定し、CSSでclass名を指定してアニーメーションの命令を書きます。
サンプル全体です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.anim1 {
    stroke: #000000;
    stroke-dasharray: 2000;
    stroke-dashoffset: 0;
    stroke-width: 1;
    -webkit-animation: test_anim1 10s ease-in 0s;
    animation: test_anim1 10s ease-in 0s;
}
@-webkit-keyframes test_anim1 {
    0% {
        stroke-dashoffset: 2000;
    }
    100% {
        stroke-dashoffset: 0;
    }
}
</style>

</head>
<body>
 
<svg width="500" height="300" viewBox="0 0 500 300">
    <polygon
        class="anim1"
        points="10 15 25 120 50 180 75 95 98 250 105 140 130 175 135 210 150 135"
        stroke="#000000"
        stroke-width="1"
        fill="none"
    />
</svg>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

画面にアクセスすると、多角形の頂点の座標から順に stroke が描画されることがわかります。

CSSの記述は以下です。

<style>
.anim1 {
    stroke: #000000;
    stroke-dasharray: 2000;
    stroke-dashoffset: 0;
    stroke-width: 1;
    -webkit-animation: test_anim1 10s ease-in 0s;
    animation: test_anim1 10s ease-in 0s;
}
@-webkit-keyframes test_anim1 {
    0% {
        stroke-dashoffset: 2000;
    }
    100% {
        stroke-dashoffset: 0;
    }
}
</style>

アニメーションの命令部分は「-webkit-animation: test_anim1 10s ease-in 0s;」と「animation: test_anim1 10s ease-in 0s;」から
「test_anim1」の指定で、「@-webkit-keyframes test_anim1」以下の内容を描画しています。

アニメーション開始時には「0%」のタグの内容を描画し、「10s」で10秒かけて「100%」のタグの内容までアニメーション描画をしています。

画面アクセスすると、線が徐々に描画されるように見えますが、これは「stroke-dashoffset」の破線の間隔を徐々に小さくなるように変化させている為、
線が描画されているように見えます。

試しに、上記のtest2.htmlのサンプルの内容を、以下のように変更してみます。

stroke-dasharray: 2000;
を、↓に変更
stroke-dasharray: 10;

-webkit-animation: test_anim1 10s ease-in 0s;
animation: test_anim1 10s ease-in 0s;
を、↓に変更
-webkit-animation: test_anim1 50s ease-in 0s;
animation: test_anim1 50s ease-in 0s;

全体的には以下になります。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.anim1 {
    stroke: #000000;
    stroke-dasharray: 10;
    stroke-dashoffset: 0;
    stroke-width: 1;
    -webkit-animation: test_anim1 50s ease-in 0s;
    animation: test_anim1 50s ease-in 0s;
}
@-webkit-keyframes test_anim1 {
    0% {
        stroke-dashoffset: 2000;
    }
    100% {
        stroke-dashoffset: 0;
    }
}
</style>

</head>
<body>
 
<svg width="500" height="300" viewBox="0 0 500 300">
    <polygon
        class="anim1"
        points="10 15 25 120 50 180 75 95 98 250 105 140 130 175 135 210 150 135"
        stroke="#000000"
        stroke-width="1"
        fill="none"
    />
</svg>

</body>
</html>

サーバ上のHTMLはこちら(test2_1.html)

画面にアクセスすると、さきほどのサンプルと同様の多角形の線分が10ピクセル単位の破線になり、その破線の「stroke-dashoffset: 2000;」が50秒の間で「stroke-dashoffset: 0;」に変化する。
という出力結果になります。

同じ内容のアニメーション指定方法ですが、パラメータが異なると描画のされ方も大きく異なることがわかります。

同様に、円(circle)のパス情報に対しても、同じCSSのパラメータ変化によるアニメーションを試してみます。

サンプルの多角形のSVGの箇所を、下記の円(circle)のパスに置き換えてみます。

<svg width="500" height="300" viewBox="0 0 500 300">
    <circle
	    class="anim1"
        cx="110"
        cy="110"
        r="100"
        stroke="#000000"
        stroke-width="1"
	    fill="none"
    />
</svg>

全体のサンプルは以下です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.anim1 {
    stroke: #000000;
    stroke-dasharray: 2000;
    stroke-dashoffset: 0;
    stroke-width: 1;
    -webkit-animation: test_anim1 10s ease-in 0s;
    animation: test_anim1 10s ease-in 0s;
}
@-webkit-keyframes test_anim1 {
    0% {
        stroke-dashoffset: 2000;
    }
    100% {
        stroke-dashoffset: 0;
    }
}
</style>

</head>
<body>
 
<svg width="500" height="300" viewBox="0 0 500 300">
    <circle
	    class="anim1"
        cx="110"
        cy="110"
        r="100"
        stroke="#000000"
        stroke-width="1"
	    fill="none"
    />
</svg>

</body>
</html>

サーバ上のHTMLはこちら(test3.html)

画面にアクセスすると、円(circle)のパスが起点から、時計回りに360度の線分が描画されることがわかります。

SVGアニメーション

Posted コメントするカテゴリー: javascript

SVGアニメーション

SVG要素をアニメーションする方法を試します。
アニメーションする方法は大きく以下の方法です。

1.CSSアニメーション要素を使う
2.SVGのDOMを利用する(CSS、javascriptの組合せ)
3.SMILを使う

ひとつひとつ順に試してみようと思います。

クリッピング mask 要素について(その6) maskContentUnits

Posted コメントするカテゴリー: javascript

クリッピング mask 要素について(その6) maskContentUnits

mask要素に対して、maskContentUnitsの指定方法を試してみます。

前回投稿のmaskUnitsと記述は似ているので、同じサンプルを使って比較してみます。

効果としてはmask要素の内容をどのように指定(座標指定か%指定か)するかを決定します。

maskUnitsと同様に、maskContentUnitsも下記の指定方法です。

 objectBoundingBox(デフォルト)はマスク領域を %指定 します。
 userSpaceOnUseはマスク領域を座標指定します。

今回はサンプルを2ファイル用意しました。
1つ目は「objectBoundingBox」のサンプルで、
2つ目は「userSpaceOnUse」のサンプルです。

まず最初は「objectBoundingBox」のサンプルです。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
 
<style>
.params_box {
    font-size : 0.8em;
}
.range {
    width: 400px;
}
.code_view {
    font-size : 0.8em;
    padding: 5px;
    background-color: #000000;
    color: #ffffff;
}
#code_view1, #code_view2, #code_view3, #code_view4 {
    color: #ff0000;
}
</style>
 
</head>
<body>
 
<svg width="500" height="300" viewBox="0 0 500 300">
    <defs>
        <mask
            id="test_mask_dom1"
            maskContentUnits="objectBoundingBox"
        >
            <rect
                id     ="mask_rect"
                x      ="38%"
                y      ="31%"
                width  ="23%"
                height ="23%"
                fill   ="#ffffff"
            />
        </mask>
    </defs>
 
    <image href="./sima.jpg" mask="url(#test_mask_dom1)" />
 
</svg>
 
<div>
    <div class="params_box">
        <span>param1 : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="38" max="100"></div>
    </div>
 
    <div class="params_box">
        <span>param2 : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="31" max="100"></div>
    </div>
 
    <div class="params_box">
        <span>param3 : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="23" max="100"></div>
    </div>
 
    <div class="params_box">
        <span>param4 : <span class="params" id="range4_value"></span></span>
        <div><input type="range" class="range" id="range4" value="23" max="100"></div>
    </div>
</div>
 
<div class="code_view">
&lt;mask<br />
&lt;rect<br />
  id     ="mask_rect"<br />
  x      ="<span id="code_view1"></span>"<br />
  y      ="<span id="code_view2"></span>"<br />
  width  ="<span id="code_view3"></span>"<br />
  height ="<span id="code_view4"></span>"<br />
  fill   ="#ffffff"<br />
/&gt;<br />
</div>
 
<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
 
// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
 
// スライダーを動かした時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);
    console.log("range4_dom.value -> " + range4_dom.value);
 
    // マスク要素を取得する
    let mask_rect = document.getElementById('mask_rect');
 
    // マスク要素の x, y, width, height のパラメータを「%指定」で動的に変更する
    mask_rect.setAttribute('x'     , (range1_dom.value) / 100);
    mask_rect.setAttribute('y'     , (range2_dom.value) / 100);
    mask_rect.setAttribute('width' , (range3_dom.value) / 100);
    mask_rect.setAttribute('height', (range4_dom.value) / 100);
 
    // パラメータ値を出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');
 
    range1_value_dom.innerHTML = range1_dom.value + '%';
    range2_value_dom.innerHTML = range2_dom.value + '%';
    range3_value_dom.innerHTML = range3_dom.value + '%';
    range4_value_dom.innerHTML = range4_dom.value + '%';
 
    // DOM要素 「id="dom_ellipse" 」の cx, cy, rx, ry のパラメータを出力する
    let code_view1_dom = document.getElementById('code_view1');
    let code_view2_dom = document.getElementById('code_view2');
    let code_view3_dom = document.getElementById('code_view3');
    let code_view4_dom = document.getElementById('code_view4');
    code_view1_dom.innerHTML = range1_dom.value + '%';
    code_view2_dom.innerHTML = range2_dom.value + '%';
    code_view3_dom.innerHTML = range3_dom.value + '%';
    code_view4_dom.innerHTML = range4_dom.value + '%';
}
 
</script>
 
</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、画像にrect要素のマスクがかかっています。

スライダーで x、y、width、height の各パラメータを動的に変更でき、
各パラメータの値が「%指定」されていることがわかります。

%指定 なので、SVGの出力領域に対して何% かで計算されていることがわかります。

以下は出力例です。

次に、「userSpaceOnUse」のサンプルです。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
 
<style>
.params_box {
    font-size : 0.8em;
}
.range {
    width: 400px;
}
.code_view {
    font-size : 0.8em;
    padding: 5px;
    background-color: #000000;
    color: #ffffff;
}
#code_view1, #code_view2, #code_view3, #code_view4 {
    color: #ff0000;
}
</style>
 
</head>
<body>
 
<svg width="500" height="300" viewBox="0 0 500 300">
    <defs>
        <mask
            id="test_mask_dom1"
            maskContentUnits="userSpaceOnUse"
        >
            <rect
                id     ="mask_rect"
                x      ="181"
                y      ="95"
                width  ="59"
                height ="42"
                fill   ="#cccccc"
            />
        </mask>
    </defs>
 
    <image href="./sima.jpg" mask="url(#test_mask_dom1)" />
 
</svg>
 
<div>
    <div class="params_box">
        <span>param1 : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="181" max="500"></div>
    </div>
 
    <div class="params_box">
        <span>param2 : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="95" max="300"></div>
    </div>
 
    <div class="params_box">
        <span>param3 : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="59" max="100"></div>
    </div>
 
    <div class="params_box">
        <span>param4 : <span class="params" id="range4_value"></span></span>
        <div><input type="range" class="range" id="range4" value="42" max="100"></div>
    </div>
</div>
 
<div class="code_view">
&lt;mask<br />
&lt;rect<br />
  id     ="mask_rect"<br />
  x      ="<span id="code_view1"></span>"<br />
  y      ="<span id="code_view2"></span>"<br />
  width  ="<span id="code_view3"></span>"<br />
  height ="<span id="code_view4"></span>"<br />
  fill   ="#ffffff"<br />
/&gt;<br />
</div>
 
<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
 
// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
 
// スライダーを動かした時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);
    console.log("range4_dom.value -> " + range4_dom.value);
 
    // マスク要素を取得する
    let mask_rect = document.getElementById('mask_rect');
 
    // マスク要素の x, y, width, height のパラメータを「%指定」で動的に変更する
    mask_rect.setAttribute('x'     , range1_dom.value);
    mask_rect.setAttribute('y'     , range2_dom.value);
    mask_rect.setAttribute('width' , range3_dom.value);
    mask_rect.setAttribute('height', range4_dom.value);
 
    // パラメータ値を出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');
 
    range1_value_dom.innerHTML = range1_dom.value;
    range2_value_dom.innerHTML = range2_dom.value;
    range3_value_dom.innerHTML = range3_dom.value;
    range4_value_dom.innerHTML = range4_dom.value;
 
    // DOM要素 「id="dom_ellipse" 」の cx, cy, rx, ry のパラメータを出力する
    let code_view1_dom = document.getElementById('code_view1');
    let code_view2_dom = document.getElementById('code_view2');
    let code_view3_dom = document.getElementById('code_view3');
    let code_view4_dom = document.getElementById('code_view4');
    code_view1_dom.innerHTML = range1_dom.value;
    code_view2_dom.innerHTML = range2_dom.value;
    code_view3_dom.innerHTML = range3_dom.value;
    code_view4_dom.innerHTML = range4_dom.value;
}
 
</script>
 
</body>
</html>

サーバ上のHTMLはこちら(test2.html)

画面にアクセスすると、1つ目のサンプルと同様に画像にrect要素のマスクがかかっています。

スライダーで x、y、width、height の各パラメータを動的に変更でき、
各パラメータの値が「座標指定」されていることがわかります。

座標指定 なので、SVGの出力領域に対しての座標でマスク領域が変化することがわかります。

以下は出力例です。

クリッピング mask 要素について(その5) maskUnits

Posted コメントするカテゴリー: javascript

クリッピング mask 要素について(その5) maskUnits

mask要素に対して、maskUnitsの指定方法を試してみます。

maskUnitsは、maskがどの座標系で影響するかを指定します。

 objectBoundingBox(デフォルト)はマスク領域を%指定します。
 userSpaceOnUseはマスク領域を座標指定します。

前の投稿のサンプルをもとに、maskUnitsの指定を試してみます。

今回のサンプルはuserSpaceOnUseを指定しているので、座標指定をしています。
全体のサンプルは以下です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
 
<style>
.params_box {
    font-size : 0.8em;
}
.range {
    width: 400px;
}
.code_view {
    font-size : 0.8em;
    padding: 5px;
    background-color: #000000;
    color: #ffffff;
}
#code_view1, #code_view2, #code_view3, #code_view4 {
    color: #ff0000;
}
</style>
 
</head>
<body>
 
<svg width="500" height="300" viewBox="0 0 500 300">
    <defs>
        <mask
            id="test_mask_dom1"
            maskUnits="userSpaceOnUse"
            x="25%"
            y="25%"
            width="40%"
            height="40%"
        >
            <path 
                d            = "M 60,50 130,210 190,60 60,50"
                fill         = "#cccccc"
                fill-opacity = "0.4"
            />
            <path 
                d            = "M 90,70 160,230 220,80 90,70"
                fill         = "#cccccc"
                fill-opacity = "0.4"
            />
            <path 
                d            = "M 120,90 190,250 250,100 120,90"
                fill         = "#cccccc"
                fill-opacity = "0.4"
            />
            <path 
                d            = "M 150,110 220,270 280,120 150,110"
                fill         = "#cccccc"
                fill-opacity = "0.4"
            />
        </mask>
    </defs>
 
    <image href="./sima.jpg" mask="url(#test_mask_dom1)" />
 
</svg>
 
<div>
    <div class="params_box">
        <span>param1 : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="25" max="500"></div>
    </div>
 
    <div class="params_box">
        <span>param2 : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="25" max="300"></div>
    </div>
 
    <div class="params_box">
        <span>param3 : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="60" max="500"></div>
    </div>
 
    <div class="params_box">
        <span>param4 : <span class="params" id="range4_value"></span></span>
        <div><input type="range" class="range" id="range4" value="60" max="300"></div>
    </div>
</div>
 
<div class="code_view">
&lt;mask<br />
  id="test_mask_dom1"<br />
  maskUnits="userSpaceOnUse"<br />
  x="<span id="code_view1"></span>"<br />
  y="<span id="code_view2"></span>"<br />
  width="<span id="code_view3"></span>"<br />
  height="<span id="code_view4"></span>"<br />
&gt;<br />
  &lt;path <br />
    d = "M 60,50 130,210 190,60 60,50"<br />
    fill = "#cccccc"<br />
    fill-opacity = "0.4"<br />
  /&gt;<br />
  &lt;path <br />
    d = "M 90,70 160,230 220,80 90,70"<br />
    fill = "#cccccc"<br />
    fill-opacity = "0.4"<br />
  /&gt;<br />
  &lt;path <br />
    d = "M 120,90 190,250 250,100 120,90"<br />
    fill = "#cccccc"<br />
    fill-opacity = "0.4"<br />
  /&gt;<br />
  &lt;path <br />
    d = "M 150,110 220,270 280,120 150,110"<br />
    fill = "#cccccc"<br />
    fill-opacity = "0.4"<br />
  /&gt;<br />
&lt;/mask&gt;
</div>
 
<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
 
// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
 
// スライダーを動かした時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);
    console.log("range4_dom.value -> " + range4_dom.value);
 
    // マスク要素を取得する
    let test_mask_dom1 = document.getElementById('test_mask_dom1');
    console.log("test_mask_dom1 -> " + test_mask_dom1);
 
    // マスク要素の x, y, width, height のパラメータを「%指定」で動的に変更する
    test_mask_dom1.setAttribute('x'     , range1_dom.value);
    test_mask_dom1.setAttribute('y'     , range2_dom.value);
    test_mask_dom1.setAttribute('width' , range3_dom.value);
    test_mask_dom1.setAttribute('height', range4_dom.value);
 
    // パラメータ値を出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');
 
    range1_value_dom.innerHTML = range1_dom.value;
    range2_value_dom.innerHTML = range2_dom.value;
    range3_value_dom.innerHTML = range3_dom.value;
    range4_value_dom.innerHTML = range4_dom.value;
 
    // DOM要素 「id="dom_ellipse" 」の cx, cy, rx, ry のパラメータを出力する
    let code_view1_dom = document.getElementById('code_view1');
    let code_view2_dom = document.getElementById('code_view2');
    let code_view3_dom = document.getElementById('code_view3');
    let code_view4_dom = document.getElementById('code_view4');
    code_view1_dom.innerHTML = range1_dom.value;
    code_view2_dom.innerHTML = range2_dom.value;
    code_view3_dom.innerHTML = range3_dom.value;
    code_view4_dom.innerHTML = range4_dom.value;
}
 
</script>
 
</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、画像に対してマスクが4つかかっている出力が確認できます。

また、 x、y、width、height の各パラメータがあり、スライダーで動的に変更できます。

スライダーを変更すると、

<mask
  id="test_mask_dom1"
  maskUnits="userSpaceOnUse"
  x="12"
  y="25"
  width="60"
  height="60"
>

mask指定の x、y、width、height の値を0~100までの「座標指定」でマスクされていることがわかります。

クリッピング mask 要素について(その4) テキストに適用する

Posted コメントするカテゴリー: javascript

クリッピング mask 要素について(その4) テキストに適用する

mask要素をテキストに適用して試してみます。

まず、テキストタグを用意します。

<text
    id="Text"
    x="120"
    y="60"
    font-size="20"
    text-anchor="middle"
>
    テストテキストA
</text>

このテキストタグのIDを、use で指定します。

<use xlink:href="#Text" fill="#ff0000" mask="url(#Mask)" />

上記の例では、「mask=”url(#Mask)”」という箇所で、マスク要素を指定しています。

マスク要素は、以下のように指定します。

<mask
    id="Mask"
    maskUnits="userSpaceOnUse"
    x="0"
    y="0"
    width="300"
    height="100"
>
    <rect x="0" y="0" width="300" height="100" fill="#eeeeee" />
</mask>

ここでポイントとなるのは、マスク要素にrectを指定して、長方形の形でマスクし、
その配色は「fill=”#eeeeee”」で指定しています。
この配色が黒に近いか、白に近いかで、マスクのかかり具合が決まります。

下記の例では、マスク要素を3つ用意し、それぞれ以下の色を指定しています。
「#eeeeee」(白に近い色)
「#9b9b9b」(グレー)
「#565656」(黒に近い色)

全体のサンプルは以下です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

</head>
<body>

<svg width="300" height="100" viewBox="0 0 300 100">
    <defs>
        <mask
            id="Mask"
            maskUnits="userSpaceOnUse"
            x="0"
            y="0"
            width="300"
            height="100"
        >
            <rect x="0" y="0" width="300" height="100" fill="#eeeeee" />
        </mask>
        <text
            id="Text"
            x="120"
            y="60"
            font-size="20"
            text-anchor="middle"
        >
            テストテキストA
        </text>
    </defs>
    <use xlink:href="#Text" fill="#ff0000" mask="url(#Mask)" />
</svg>

<svg width="300" height="100" viewBox="0 0 300 100">
    <defs>
        <mask
            id="Mask2"
            maskUnits="userSpaceOnUse"
            x="0"
            y="0"
            width="300"
            height="100"
        >
            <rect x="0" y="0" width="300" height="100" fill="#9b9b9b" />
        </mask>
        <text
            id="Text2"
            x="120"
            y="60"
            font-size="20"
            text-anchor="middle"
        >
            テストテキストB
        </text>
    </defs>
    <use xlink:href="#Text2" fill="#ff0000" mask="url(#Mask2)" />
</svg>

<svg width="300" height="100" viewBox="0 0 300 100">
    <defs>
        <mask
            id="Mask3"
            maskUnits="userSpaceOnUse"
            x="0"
            y="0"
            width="300"
            height="100"
        >
            <rect x="0" y="0" width="300" height="100" fill="#565656" />
        </mask>
        <text
            id="Text3"
            x="120"
            y="60"
            font-size="20"
            text-anchor="middle"
        >
            テストテキストC
        </text>
    </defs>
    <use xlink:href="#Text3" fill="#ff0000" mask="url(#Mask3)" />
</svg>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、3つのテキスト要素に対して、(異なるfillの値で)マスクされたテキスト文字が出力されていることがわかります。

また、マスクのかかり具合は、黒に近づくにつれて強くかかっていることが確認できます。

クリッピング mask 要素について(その3) fill-opacity で透明度を指定する

Posted コメントするカテゴリー: javascript

クリッピング mask 要素について(その3) fill-opacity で透明度を指定する

mask要素に fill-opacity を指定して、効果を透明にすることができます。

前回同様に鳥の画像に対して、fill-opacity の値を0.4に指定したマスクを4つ用意しました。

また、4つのマスク要素はそれぞれ重なるように配置し、重なった部分のマスクがどのように出力されるのかを見てみます。

全体のサンプルは以下です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

</head>
<body>

<svg width="500" height="300" viewBox="0 0 500 300">
    <defs>
        <mask id="test_mask_dom1">
            <path 
                d            = "M 60,50 130,210 190,60 60,50"
                fill         = "#cccccc"
                fill-opacity = "0.4"
            />
            <path 
                d            = "M 90,70 160,230 220,80 90,70"
                fill         = "#cccccc"
                fill-opacity = "0.4"
            />
            <path 
                d            = "M 120,90 190,250 250,100 120,90"
                fill         = "#cccccc"
                fill-opacity = "0.4"
            />
            <path 
                d            = "M 150,110 220,270 280,120 150,110"
                fill         = "#cccccc"
                fill-opacity = "0.4"
            />
        </mask>
    </defs>

    <image href="./sima.jpg" mask="url(#test_mask_dom1)" />

</svg>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、元画像に対して fill-opacity を指定したことにより透明になったマスクがされていることがわかります。

また、マスク同士が重なっている箇所については、重なった部分のみマスクの値が軽減され、元画像がくっきりと表示されることもわかります。(キャプチャ参照)

クリッピング mask 要素について(その2) グラデーション

Posted コメントするカテゴリー: javascript

クリッピング mask 要素について(その2) グラデーション

クリッピングのmask要素をグラデーションにした場合を試してみます。

前回同様に鳥の画像に対して、radialGradient 指定したDOMを作成し、
その内部に2つの異なる色要素を指定してグラデーションを用意します。

<radialGradient id="radial_gradient1">
    <stop offset="35%" stop-color="#333" id="gradient_offset1" />
    <stop offset="70%" stop-color="#fff" id="gradient_offset2" />
</radialGradient>

また、以下のマスク要素のDOMを用意します。
この要素のfillには「fill = “url(#radial_gradient1)”」として、
上記のradialGradientで用意したグラデーション要素のIDを指定しています。

<mask id="test_mask">
    <path
        id           = "test_mask_dom1"
        d            = "M 50,250 400,200 110,5 Z"
        stroke       = "#999999"
        stroke-width = "1"
        fill         = "url(#radial_gradient1)"
    />
</mask>

上記の2つの要素を組み合わせ、マスク要素にグラデーションがどのように
効果するのかを試してみます。

全体のサンプルは以下です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
    font-size: 0.8em;
}
.range {
    width: 400px;
}
.code_view {
    font-size: 0.8em;
    padding: 5px;
    background-color: #000000;
    color: #ffffff;
}
#code_view1, #code_view2, #code_view3 {
    color: #ff0000;
}
</style>

</head>
<body>

<svg width="500" height="300" viewBox="0 0 500 300">
    <defs>

        <radialGradient id="radial_gradient1">
            <stop offset="35%" stop-color="#333" id="gradient_offset1" />
            <stop offset="70%" stop-color="#fff" id="gradient_offset2" />
        </radialGradient>

        <mask id="test_mask">
            <path
                id           = "test_mask_dom1"
                d            = "M 50,250 400,200 110,5 Z"
                stroke       = "#999999"
                stroke-width = "1"
                fill         = "url(#radial_gradient1)"
            />
        </mask>

    </defs>

    <image href="./sima.jpg" mask="url(#test_mask)"/>

</svg>

<div>
    <div class="params_box">
        <span>param1 (グラデーションの色指定1) : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="35" max="100"></div>
    </div>

    <div class="params_box">
        <span>param2 (グラデーションの色指定2) : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="70" max="100"></div>
    </div>

    <div class="params_box">
        <span>param3 マスクの座標指定1のx座標) : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="50" max="500"></div>
    </div>

    <div class="params_box">
        <span>param4 マスクの座標指定1のy座標) : <span class="params" id="range4_value"></span></span>
        <div><input type="range" class="range" id="range4" value="250" max="500"></div>
    </div>

    <div class="params_box">
        <span>param5 マスクの座標指定2のx座標) : <span class="params" id="range5_value"></span></span>
        <div><input type="range" class="range" id="range5" value="400" max="500"></div>
    </div>

    <div class="params_box">
        <span>param6 マスクの座標指定2のy座標) : <span class="params" id="range6_value"></span></span>
        <div><input type="range" class="range" id="range6" value="200" max="500"></div>
    </div>

    <div class="params_box">
        <span>param7 マスクの座標指定3のx座標) : <span class="params" id="range7_value"></span></span>
        <div><input type="range" class="range" id="range7" value="110" max="500"></div>
    </div>

    <div class="params_box">
        <span>param8 マスクの座標指定3のy座標) : <span class="params" id="range8_value"></span></span>
        <div><input type="range" class="range" id="range8" value="5" max="500"></div>
    </div>
</div>

<div class="code_view">
&lt;svg width="500" height="300" viewBox="0 0 500 300"&gt;<br />
    &lt;defs&gt;<br /><br />

        &lt;radialGradient id="radial_gradient1"&gt;<br />
            &lt;stop offset="<span id="code_view1"></span>%" stop-color="#333" id="gradient_offset1" /&gt;<br />
            &lt;stop offset="<span id="code_view2"></span>%" stop-color="#fff" id="gradient_offset2" /&gt;<br />
         &lt;/radialGradient&gt;<br /><br />

        &lt;mask id="test_mask_dom1"&gt;<br />
            &lt;path <br />
                d            = "<span id="code_view3"></span>"<br />
                stroke       = "#999999"<br />
                stroke-width = "1"<br />
                fill         = "url(#radial_gradient1)"<br />
            /&gt;<br />
        &lt;/mask&gt;<br />
    &lt;/defs&gt;<br /><br />

    &lt;image href="./sima.jpg" mask="url(#test_mask_dom1)"/&gt;<br />

&lt;/svg&gt;
</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
let range5_dom = document.getElementById('range5');
let range6_dom = document.getElementById('range6');
let range7_dom = document.getElementById('range7');
let range8_dom = document.getElementById('range8');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
range5_dom.addEventListener('input', change_range_slider);
range6_dom.addEventListener('input', change_range_slider);
range7_dom.addEventListener('input', change_range_slider);
range8_dom.addEventListener('input', change_range_slider);

// スライダーを動かした時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);
    console.log("range4_dom.value -> " + range4_dom.value);
    console.log("range5_dom.value -> " + range5_dom.value);
    console.log("range6_dom.value -> " + range6_dom.value);
    console.log("range7_dom.value -> " + range7_dom.value);
    console.log("range8_dom.value -> " + range8_dom.value);

    // クリップする側の要素を取得する
    let dom_gradient_offset1 = document.getElementById('gradient_offset1');
    let dom_gradient_offset2 = document.getElementById('gradient_offset2');
    console.log("dom_gradient_offset1 -> " + dom_gradient_offset1);
    console.log("dom_gradient_offset1 -> " + dom_gradient_offset1);

    // DOM要素 「id="dom_radial_gradient1" 」の offset値 を動的に変更する
    dom_gradient_offset1.setAttribute('offset', range1_dom.value + '%');
    dom_gradient_offset2.setAttribute('offset', range2_dom.value + '%');

	// マスク要素の d の値を動的に変更する
	// dの値は3点をとり、三角形のマスク領域を指定する
    let dom_test_mask_dom1 = document.getElementById('test_mask_dom1');

    // DOM要素 「id="test_mask_dom1" 」の d のパラメータを決定する
    let d_value = 'M ' + range3_dom.value + ', ' + range4_dom.value + ' '
                       + range5_dom.value + ', ' + range6_dom.value + ' '
                       + range7_dom.value + '  ' + range8_dom.value + ' Z';

    // SVG要素の d の値を設定する
    dom_test_mask_dom1.setAttribute('d', d_value);

    // パラメータ値を出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');
    let range5_value_dom = document.getElementById('range5_value');
    let range6_value_dom = document.getElementById('range6_value');
    let range7_value_dom = document.getElementById('range7_value');
    let range8_value_dom = document.getElementById('range8_value');

    range1_value_dom.innerHTML = range1_dom.value;
    range2_value_dom.innerHTML = range2_dom.value;
    range3_value_dom.innerHTML = range3_dom.value;
    range4_value_dom.innerHTML = range4_dom.value;
    range5_value_dom.innerHTML = range5_dom.value;
    range6_value_dom.innerHTML = range6_dom.value;
    range7_value_dom.innerHTML = range7_dom.value;
    range8_value_dom.innerHTML = range8_dom.value;

    // DOM要素 「id="radial_gradient1" 」の offset 値をパラメータを出力する
    // また、マスク要素の d の値も同様に出力する
    let code_view1_dom = document.getElementById('code_view1');
    let code_view2_dom = document.getElementById('code_view2');
    let code_view3_dom = document.getElementById('code_view3');

    // 画面上のコード欄に値を出力する
    code_view1_dom.innerHTML = range1_dom.value;
    code_view2_dom.innerHTML = range2_dom.value;
    code_view3_dom.innerHTML = d_value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、もとの画像に対して、マスク要素内にグラデーション指定した効果がかかっていることがわかります。

グラデーションの濃さ(0~100%)の指定は今回のサンプルでは、常にマスク要素の中心にかかっています。

また、マスク要素の三角形の位置を変化されると、グラデーション効果の位置も併せて変化する(常に中心からグラデーションする)こともわかります。

以下は3パターンの出力例をキャプチャしたものです。

サンプルHTMLの画面から、実際にパラメータを変化させてみるとどのような効果になるのかがわかります。

出力サンプル1

出力サンプル2

出力サンプル3

クリッピング mask 要素について

Posted コメントするカテゴリー: javascript

クリッピング mask 要素について

クリッピングのmask要素を試してみます。

まずは、もっともシンプルな基画像をmask要素を指定したSVGでmaskする方法です。

全体のサンプルは以下です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

</head>
<body>

<svg width="500" height="300" viewBox="0 0 500 300">
    <defs>
        <mask id="test_mask_dom1">
            <path 
                d            = "M 10,10 90,150 120,20 10,10"
                stroke       = "#999999"
                stroke-width = "1"
                fill         = "#434343"
            />
            <path 
                d            = "M 60,60 140,200 170,70 60,60"
                stroke       = "#999999"
                stroke-width = "1"
                fill         = "#848484"
            />
            <path 
                d            = "M 110,110 190,250 220,120 110,110"
                stroke       = "#999999"
                stroke-width = "1"
                fill         = "#cfcfcf"
            />
        </mask>
    </defs>

    <image href="./sima.jpg" mask="url(#test_mask_dom1)"/>

</svg>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、基画像に対して、3つのSVG要素でmaskをしていることがわかります。

また、それぞれのSVG要素には

                fill         = "#434343"

                fill         = "#848484"

                fill         = "#cfcfcf"

というfillの色指定をしており、上から順に「うすい黒 → 中間の薄さ → うすい白」という色合いになっています。

サンプルの出力から、mask要素は、白に近づくにつれて基画像がくっきりと出力される(maskの度合が薄くなる)ことがわかります。

また、黒に近いmask要素は基画像がほとんど写っていません。

このサンプルをもとにmask要素の他の効果を調べてみようと思います。

クリッピング マスキング について(その7) – clip-ruleの指定について

Posted コメントするカテゴリー: javascript

クリッピング マスキング について(その7) – clip-ruleの指定について

クリッピングパスその7は、clip-ruleの指定について試してみます。

clip-ruleは、clipPathの要素に含まれるグラフィックス要素に適用されます。
値は2種類あり、nonzero と evenodd です。(デフォルトはnonzero)

それぞれの定義を仕様から抜粋します。

nonzero

この規則においては、キャンバス上の点が「内側」にあるかどうかは、
その点から適当な方向(どの方向でも良い)へ無限遠まで伸びる射線をひき,
その射線と図形のパスとの交わり方を吟味することにより決定される。
 
パスが点から見て射線の左から右へ交差するときは 1, 
右から左へ交差するときは -1 と数え、

その総和が0のとき点はパスの外側にあるとされ, 
それ以外の場合は内側とされる

evenodd

この規則においては、キャンバス上の点が「内側」にあるかどうかは、
その点から適当な方向(どの方向でも良い)へ無限遠まで伸びる射線をひき,
その射線と図形のパスとの交わり方を吟味することにより決定される。
 
パスが点から見て射線の左から右へ交差するときは 1, 
右から左へ交差するときは -1 と数え、

その総和が偶数のとき点はパスの外側にあるとされ, 
それ以外の場合は内側とされる。

個人的には上記の文章で読んでもどのような効果があるのかがイメージしにくいと思いました。

実際にサンプルを書いて試してみます。

今回のサンプルは、基になる画像(鳥の画像)に、クリッピング対象となるパス情報でクリップするように構成されています。

例として、以下のパス情報を使って、clip-ruleの属性「nonzero」と「evenodd」の両方を出力して比較してみます。

全体のサンプルは以下です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

</head>
<body>


元のパス情報
<div>
	<svg width="500" height="180" viewBox="0 0 500 200">
	    <path 
	        d              = "M0 128 L0 0 L128 0 L128 128 L32 64 L32 32 L96 32 L96 64 Z"
	        stroke         = "#4f4f4f"
	        stroke-width   = "1"
	        fill           = "#cccccc"
	    />
	</svg>
</div>


nonzero
<div>
	<svg width="500" height="180" viewBox="0 0 500 200">
	    <defs>
	        <clipPath id="test_clip_dom2" clip-rule="nonzero">
		        <path d='M0 128 L0 0 L128 0 L128 128 L32 64 L32 32 L96 32 L96 64 Z' />
	        </clipPath>
	    </defs>
	    <image href="./sima.jpg" clip-path="url(#test_clip_dom2)"/>
	</svg>
</div>


evenodd
<div>
	<svg width="500" height="180" viewBox="0 0 500 200">
	    <defs>
	        <clipPath id="test_clip_dom1" clip-rule="evenodd">
		        <path d='M0 128 L0 0 L128 0 L128 128 L32 64 L32 32 L96 32 L96 64 Z' />
	        </clipPath>
	    </defs>
	    <image href="./sima.jpg" clip-path="url(#test_clip_dom1)"/>
	</svg>
</div>


</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、元のパス情報とevenodd指定した場合、nonzero指定した場合の比較ができます。

クリッピング マスキング について(その6) – clipPathUnitsの指定について

Posted コメントするカテゴリー: javascript

クリッピング マスキング について(その6) – clipPathUnitsの指定について

クリッピングパスその6は、clipPathUnitsの指定について試してみます。

clipPathUnitsは、clipPathのDOMを記述する際の、パラメータとして追加します。

今回のサンプルでは、以前の投稿(クリッピング マスキング について(その2) – クリッピングパスに画像を使用した場合)で使用したHTMLソースをもとに、clipPathUnitsの記述を追記して動きを確認します。

(一部抜粋)

<defs>
    <clipPath id="test_clip_dom1" clipPathUnits="objectBoundingBox">
        <path
            id="test_clip_path1"
            d='M16 238 L236 246 L242 22 Z'
            rx="0.5"
            ry="0.5"
            cx="0.5"
            cy="0.5"
            stroke="#999999"
            stroke-width="1"
            fill="#cccccc"
        />

        <ellipse
        	id="dom_ellipse"
            cx="0.5"
            cy="0.5"
            rx="0.2"
            ry="0.2"
            stroke="#000000"
            stroke-width="1"
            fill="none"
        />

    </clipPath>
</defs>

追記したパラメータは下記の場所で、

<clipPath id="test_clip_dom1" clipPathUnits="objectBoundingBox">

「clipPathUnits=”objectBoundingBox”」という指定をしています。

この記述を省略するとデフォルト値として、userSpaceOnUse という値が暗黙的に適用されます。
デフォルトの場合はクリッピングする要素を「座標の値で指定」します。

今回の例では、objectBoundingBox として、クリッピングする要素を「比率(100分率)で指定」します。

例えば、0を指定すると0%、0.5を指定すると50%、1を指定すると100%、というように作用します。

サンプルでは、スライダをつけてクリッピングする側の要素(楕円)の
「位置(x軸、y軸)」「サイズ(x軸、y軸)」を100分率で動的に確認できるものを用意しました。

下記、サンプルの全体です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
    font-size : 0.8em;
    padding-bottom: 10px;
}
.range {
    width: 400px;
}
.code_view {
    font-size : 0.8em;
    padding: 5px;
    background-color: #000000;
    color: #ffffff;
}
#code_view1, #code_view2, #code_view3, #code_view4 {
    color: #ff0000;
}
</style>

</head>
<body>

<svg width="500" height="270" viewBox="0 0 500 270">

    <defs>
        <clipPath id="test_clip_dom1" clipPathUnits="objectBoundingBox">
            <path
                id="test_clip_path1"
                d='M16 238 L236 246 L242 22 Z'
                rx="0.5"
                ry="0.5"
                cx="0.5"
                cy="0.5"
                stroke="#999999"
                stroke-width="1"
                fill="#cccccc"
            />

            <ellipse
            	id="dom_ellipse"
                cx="0.5"
                cy="0.5"
                rx="0.2"
                ry="0.2"
                stroke="#000000"
                stroke-width="1"
                fill="none"
            />

        </clipPath>
    </defs>
    
    <image href="./sima.jpg" clip-path="url(#test_clip_dom1)" width="400" height="226"/>
    
</svg>

<div>

    <div class="params_box">
        <span>param1 : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="50" max="100"></div>
    </div>

    <div class="params_box">
        <span>param2 : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="50" max="100"></div>
    </div>

    <div class="params_box">
        <span>param3 : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="20" max="100"></div>
    </div>

    <div class="params_box">
        <span>param4 : <span class="params" id="range4_value"></span></span>
        <div><input type="range" class="range" id="range4" value="20" max="100"></div>
    </div>

</div>

<div class="code_view">
&lt;clipPath id="dom_ellipse"&gt;<br />
  &lt;path<br />
    id="dom_ellipse"<br />
    cx="<span id="code_view1"></span>"<br />
    cy="<span id="code_view2"></span>"<br />
    rx="<span id="code_view3"></span>"<br />
    ry="<span id="code_view4"></span>"<br />
    stroke="#000000"<br />
    stroke-width="1"<br />
    fill="none"<br />
  /&gt;<br />
&lt;/clipPath&gt;<br />
</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);

// スライダーを動かした時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + (range1_dom.value / 100));
    console.log("range2_dom.value -> " + (range2_dom.value / 100));
    console.log("range3_dom.value -> " + (range3_dom.value / 100));
    console.log("range4_dom.value -> " + (range4_dom.value / 100));

    // クリップする側の要素を取得する
    let dom_ellipse = document.getElementById('dom_ellipse');
    console.log("dom_ellipse -> " + dom_ellipse);

    // DOM要素 「id="dom_ellipse" 」の cx, cy, rx, ry のパラメータを動的に変更する
    dom_ellipse.setAttribute('cx', (range1_dom.value / 100));
    dom_ellipse.setAttribute('cy', (range2_dom.value / 100));
    dom_ellipse.setAttribute('rx', (range3_dom.value / 100));
    dom_ellipse.setAttribute('ry', (range4_dom.value / 100));

    // パラメータ値を出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');

    range1_value_dom.innerHTML = range1_dom.value;
    range2_value_dom.innerHTML = range2_dom.value;
    range3_value_dom.innerHTML = range3_dom.value;
    range4_value_dom.innerHTML = range4_dom.value;

    // DOM要素 「id="dom_ellipse" 」の cx, cy, rx, ry のパラメータを出力する
    let code_view1_dom = document.getElementById('code_view1');
    let code_view2_dom = document.getElementById('code_view2');
    let code_view3_dom = document.getElementById('code_view3');
    let code_view4_dom = document.getElementById('code_view4');
    code_view1_dom.innerHTML = (range1_dom.value / 100);
    code_view2_dom.innerHTML = (range2_dom.value / 100);
    code_view3_dom.innerHTML = (range3_dom.value / 100);
    code_view4_dom.innerHTML = (range4_dom.value / 100);
}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、初期表示の状態で、

位置が画面全体の x = 0.5(画面の50%の大きさ) 、 y = 0.5(画面の50%の大きさ) 、
サイズが x = 0.2(画面左から20%の位置) 、 y = 0.2(画面上から20%の位置) 、に

クリッピング要素の楕円が表示されることがわかります。

また、スライダを操作すると、その下に表示されるDOM要素のソースが変化するので、
objectBoundingBox 指定時の値が100分率(%)で指定され、画面にどのように作用するかが動的にわかります。

下記は、スライダの操作例です。

クリッピング マスキング について(その5) – クリッピングパスのグループ化

Posted コメントするカテゴリー: javascript

クリッピング マスキング について(その5) – クリッピングパスのグループ化

クリッピングパスその5は、クリッピングされる対象(本サンプルでは画像)のDOM要素を、
gタグで囲い、グルーピングを行ったうえでクリッピングする例を試してみます。

一つのクリッピングする側の要素を、gタグで囲い、gタグで囲った要素をひとまとめにして制御することが可能です。

今回のサンプルでは、楕円(ellipse)を一つ用意し、

<ellipse
    id="ellipse_group"
    cx="200"
    cy="100"
    rx="100"
    ry="150"
    fill-opacity="0.2"
/>

それをgタグで囲った中で4つのクリッピング(する側)の要素として記述し、

<g clip-path="url(#test_clip_dom1)">
    <use href="#ellipse_group" x="0" y="0" fill="#808080" />
    <use href="#ellipse_group" x="0" y="0" fill="#4169e1" transform="rotate(30,120,120)" />
    <use href="#ellipse_group" x="0" y="0" fill="#3cb371" transform="rotate(60,120,120)" />
    <use href="#ellipse_group" x="0" y="0" fill="#ff0011" transform="rotate(90,120,120)" />
</g>

楕円(ellipse)のパラメータを動的にスライダで変更、確認できる画面を用意しました。

下記、サンプルの全体です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
    font-size : 0.9em;
    padding-bottom: 10px;
}
.range {
    width: 500px;
}
.code_view {
    font-size : 0.8em;
    padding: 5px;
    background-color: #000000;
    color: #ffffff;
}
#code_view1, #code_view2, #code_view3, #code_view4  {
    color: #ff0000;
}
</style>

</head>
<body>

<svg width="500" height="320" viewBox="0 0 500 320">
    <defs>
        <ellipse
            id="ellipse_group"
            cx="280"
            cy="200"
            rx="70"
            ry="70"
            fill-opacity="0.2"
        />
        <clipPath id="test_clip_dom1">
            <circle cx="160" cy="160" r="150">
        </clipPath>
    </defs>
    <g clip-path="url(#test_clip_dom1)">
        <use href="#ellipse_group" x="0" y="0" fill="#808080" />
        <use href="#ellipse_group" x="0" y="0" fill="#4169e1" transform="rotate(30,120,120)" />
        <use href="#ellipse_group" x="0" y="0" fill="#3cb371" transform="rotate(60,120,120)" />
        <use href="#ellipse_group" x="0" y="0" fill="#ff0011" transform="rotate(90,120,120)" />
    </g>

</svg>

<div>
    <div class="params_box">
        <div>
        <input type="range" class="range" id="range1" value="40" max="500">
        param1 : <span class="params" id="range1_value"></span>
        </div>

        <div>
        <input type="range" class="range" id="range2" value="140" max="500">
        param2 : <span class="params" id="range2_value"></span></span>
        </div>

        <div>
        <input type="range" class="range" id="range3" value="100" max="500">
        param3 : <span class="params" id="range3_value"></span></span>
        </div>

        <div>
        <input type="range" class="range" id="range4" value="100" max="500">
        param4 : <span class="params" id="range4_value"></span></span>
        </div>

    </div>
</div>

<div class="code_view">
&lt;ellipse<br />
  id="ellipse_group"<br />
  cx="<span id="code_view1"></span>"<br />
  cy="<span id="code_view2"></span>"<br />
  rx="<span id="code_view3"></span>"<br />
  ry="<span id="code_view4"></span>"<br />
  fill-opacity="0.2"<br />
/&gt;<br />
</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);

// スライダーを動かした時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);
    console.log("range4_dom.value -> " + range4_dom.value);

    // クリップする側の要素を取得する
    let test_clip_dom1 = document.getElementById('ellipse_group');
    console.log("test_clip_dom1 -> " + test_clip_dom1);

    // SVG要素の x y font の値を設定する
    test_clip_dom1.setAttribute('cx' , range1_dom.value);
    test_clip_dom1.setAttribute('cy' , range2_dom.value);
    test_clip_dom1.setAttribute('rx'  , range3_dom.value);
    test_clip_dom1.setAttribute('ry'  , range4_dom.value);

    // パラメータ値を出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');

    range1_value_dom.innerHTML = range1_dom.value;
    range2_value_dom.innerHTML = range2_dom.value;
    range3_value_dom.innerHTML = range3_dom.value;
    range4_value_dom.innerHTML = range4_dom.value;

    // DOM要素 「id="test_clip_dom1" 」の 各パラメータを動的に出力する
    let code_view1_dom = document.getElementById('code_view1');
    let code_view2_dom = document.getElementById('code_view2');
    let code_view3_dom = document.getElementById('code_view3');
    let code_view4_dom = document.getElementById('code_view4');
    code_view1_dom.innerHTML = range1_dom.value;
    code_view2_dom.innerHTML = range2_dom.value;
    code_view3_dom.innerHTML = range3_dom.value;
    code_view4_dom.innerHTML = range4_dom.value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、半径150ピクセル、中心位置 x:160、y:160の円に対して、
gタグで囲った中で4つのクリッピング要素をもとにクリッピングされていることがわかります。

また、スライダを動的に変更すると、クリッピングする要素がグループとして作用していることがわかります。

下記のキャプチャ例は、スライダーを調整した例です。

例1

例2

例3

例4

クリッピング マスキング について(その4) – 文字列でのクリッピングパス

Posted コメントするカテゴリー: javascript

クリッピング マスキング について(その4) – 文字列でのクリッピングパス

クリッピングパスその4はクリッピングされる対象(本サンプルでは画像)のDOM要素を、
文字列でクリッピングするサンプルを試してみます。

クリッピングされる対象と、クリッピングする対象の関係はこれまでのサンプルと同様で、
クリッピングする要素が text 要素で指定されているという違いのみになります。

下記のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
    font-size : 0.8em;
    padding-bottom: 10px;
}
.range {
    width: 400px;
}
.code_view {
    font-size : 0.8em;
    padding: 5px;
    background-color: #000000;
    color: #ffffff;
}
#code_view1, #code_view2, #code_view3  {
    color: #ff0000;
}
</style>

</head>
<body>

<svg width="500" height="250" viewBox="0 0 500 250">

    <defs>
        <clipPath id="test_clip_dom1">
            <text
                id="test_clip_path1"
                x="30"
                y="70"
                font-size="50"
                font-weight="bold"
            >enaga</text>
        </clipPath>
    </defs>
    
    <image href="./sima.jpg" clip-path="url(#test_clip_dom1)" width="400" height="226"/>
    
</svg>

<div>
    <div class="params_box">
        <span>param1 : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="40" max="500"></div>
    </div>
    <div class="params_box">
        <span>param2 : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="140" max="500"></div>
    </div>
    <div class="params_box">
        <span>param3 : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="100" max="500"></div>
    </div>
</div>

<div class="code_view">
&lt;clipPath id="test_clip_dom1"&gt;<br />
  &lt;text<br />
    id="test_clip_path1"<br />
    x = "<span id="code_view1"></span>"<br />
    y = "<span id="code_view2"></span>"<br />
    font-size ="<span id="code_view3"></span>"<br />
  /&gt;<br />
&lt;/clipPath&gt;<br />
</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);

// スライダーを動かした時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);

    // クリップする側の要素を取得する
    let test_clip_path1 = document.getElementById('test_clip_path1');
    console.log("test_clip_path1 -> " + test_clip_path1);

    // SVG要素の x y font の値を設定する
    test_clip_path1.setAttribute('x'        , range1_dom.value);
    test_clip_path1.setAttribute('y'        , range2_dom.value);
    test_clip_path1.setAttribute('font-size', range3_dom.value);

    // パラメータ値を出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');

    range1_value_dom.innerHTML = range1_dom.value;
    range2_value_dom.innerHTML = range2_dom.value;
    range3_value_dom.innerHTML = range3_dom.value;

    // DOM要素 「id="test_clip_path1" 」の 各パラメータを動的に出力する
    let code_view1_dom = document.getElementById('code_view1');
    let code_view2_dom = document.getElementById('code_view2');
    let code_view3_dom = document.getElementById('code_view3');
    code_view1_dom.innerHTML = range1_dom.value;
    code_view2_dom.innerHTML = range2_dom.value;
    code_view3_dom.innerHTML = range3_dom.value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、テキスト要素の位置、サイズにより、元画像がクリッピングされることがわかります。

下記のキャプチャ例は、スライダーを調整した一例です。

クリッピング マスキング について(その3) – 複数のクリッピングパス要素について

Posted コメントするカテゴリー: javascript

クリッピング マスキング について(その3) – 複数のクリッピングパス要素について

クリッピングについて、さらに調べてみます。

前回投稿したクリッピングの処理について、クリッピングするパスが複数あるケースを試してみます。

用意したサンプルでは、前回のスライダで動的に変更可能なパスと、ellipse(楕円)、polygon(多角形)の3つを用意しました。

ellipse(楕円)は単体で描画すると、下記のような楕円です。

<ellipse
    cx="90"
    cy="30"
    rx="80"
    ry="30"
    stroke="#000000"
    stroke-width="1"
    fill="none"
/>

また、polygon(多角形)を単体で描画すると、下記のような多角形になります。

<polygon
    points="10 15 25 120 50 180 75 95 98 250 105 140 130 175 135 210 150 135"
    stroke="#000000"
    stroke-width="1"
    fill="none"
/>

この二つのパスは、当ブログの過去に投稿した際のサンプルを流用していますが、
記述するパスは特に指定はありません。

この3つのパスを使ってクリッピングする下記のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
    font-size : 0.8em;
    padding-bottom: 10px;
}
.range {
    width: 400px;
}
.code_view {
    font-size : 0.8em;
    padding: 5px;
    background-color: #000000;
    color: #ffffff;
}
#code_view1 {
    color: #ff0000;
}
</style>

</head>
<body>

<svg width="500" height="270" viewBox="0 0 500 270">

    <defs>
        <clipPath id="test_clip_dom1">
            <path
                id="test_clip_path1"
                d='M16 238 L236 246 L242 22 Z'
                rx="150"
                ry="100"
                cx="200"
                cy="120"
                stroke="#999999"
                stroke-width="1"
                fill="#cccccc"
            />

            <ellipse
                cx="90"
                cy="30"
                rx="80"
                ry="30"
                stroke="#000000"
                stroke-width="1"
                fill="none"
            />

            <polygon
                points="10 15 25 120 50 180 75 95 98 250 105 140 130 175 135 210 150 135"
                stroke="#000000"
                stroke-width="1"
                fill="none"
            />

        </clipPath>
    </defs>
    
    <image href="./sima.jpg" clip-path="url(#test_clip_dom1)" width="400" height="226"/>
    
</svg>

<div>

    <div class="params_box">
        <span>param1 : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>param2 : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>param3 : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>param4 : <span class="params" id="range4_value"></span></span>
        <div><input type="range" class="range" id="range4" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>param5 : <span class="params" id="range5_value"></span></span>
        <div><input type="range" class="range" id="range5" value="300" max="500"></div>
    </div>

    <div class="params_box">
        <span>param6 : <span class="params" id="range6_value"></span></span>
        <div><input type="range" class="range" id="range6" value="200" max="500"></div>
    </div>

</div>

<div class="code_view">
&lt;clipPath id="test_clip_dom1"&gt;<br />
  &lt;path<br />
    id="test_clip_path1"<br />
    d = "<span id="code_view1"></span>"<br />
    rx="150"<br />
    ry="100"<br />
    cx="200"<br />
    cy="120"<br />
    stroke="#999999"<br />
    stroke-width="1"<br />
    fill="#cccccc"<br />
  /&gt;<br />
&lt;/clipPath&gt;<br />
</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
let range5_dom = document.getElementById('range5');
let range6_dom = document.getElementById('range6');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
range5_dom.addEventListener('input', change_range_slider);
range6_dom.addEventListener('input', change_range_slider);

// スライダーを動かした時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);
    console.log("range4_dom.value -> " + range4_dom.value);
    console.log("range5_dom.value -> " + range5_dom.value);
    console.log("range6_dom.value -> " + range6_dom.value);

    // クリップする側の要素を取得する
    let test_clip_path1 = document.getElementById('test_clip_path1');
    console.log("test_clip_path1 -> " + test_clip_path1);

    let d_value = '';
    
    // DOM要素 「id="test_clip_path1" 」の d のパラメータ
    d_value = 'M' + range1_dom.value + ' ' + range2_dom.value
            + ' L' + range3_dom.value + ' ' + range4_dom.value
            + ' L' + range5_dom.value + ' ' + range6_dom.value
            + ' Z';

    // SVG要素の d の値を設定する
    test_clip_path1.setAttribute('d', d_value);

    // パラメータ値を出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');
    let range5_value_dom = document.getElementById('range5_value');
    let range6_value_dom = document.getElementById('range6_value');

    range1_value_dom.innerHTML = range1_dom.value;
    range2_value_dom.innerHTML = range2_dom.value;
    range3_value_dom.innerHTML = range3_dom.value;
    range4_value_dom.innerHTML = range4_dom.value;
    range5_value_dom.innerHTML = range5_dom.value;
    range6_value_dom.innerHTML = range6_dom.value;

    // DOM要素 「id="test_clip_path1" 」の d のパラメータを動的に出力する
    let code_view1_dom = document.getElementById('code_view1');
    code_view1_dom.innerHTML = d_value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、3つのパス要素が出力され、元画像の表示をクリッピングしていることがわかります。

このように1つのパスでは表現が難しいクリッピングを、複数のパスで実現することができます。

クリッピング マスキング について(その2) – クリッピングパスに画像を使用した場合

Posted コメントするカテゴリー: javascript

クリッピング マスキング について(その2) – クリッピングパスに画像を使用した場合

クリッピングについて、さらに調べてみます。

クリッピングは「元(クリップされる側)のDOM要素を、クリップする側の要素で、切り抜く」ような動きをすると言えます。
前回のサンプルでは、元のDOM要素も、クリップする側の要素も図形の要素を用いていたので、切り抜く側、切り抜かれる側の区別が把握しずらかったです。

今回は、クリップされる側(元のDOM要素)に画像を使って、動きを見てみます。

元の画像は、下記のようなjpg画像(サイズは、横400px 縦266px)を用意しました。

次に、その画像をクリッピングする下記のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
    font-size : 0.8em;
    padding-bottom: 10px;
}
.range {
    width: 400px;
}
.code_view {
    font-size : 0.8em;
    padding: 5px;
    background-color: #000000;
    color: #ffffff;
}
#code_view1 {
    color: #ff0000;
}
</style>

</head>
<body>

<svg width="500" height="270" viewBox="0 0 500 270">

    <defs>
        <clipPath id="test_clip_dom1">
            <path
                id="test_clip_path1"
                d='M16 238 L236 246 L242 22 Z'
                rx="150"
                ry="100"
                cx="200"
                cy="120"
                stroke="#999999"
                stroke-width="1"
                fill="#cccccc"
            />
        </clipPath>
    </defs>
    
    <image href="./sima.jpg" clip-path="url(#test_clip_dom1)" width="400" height="226"/>
    
</svg>

<div>

    <div class="params_box">
        <span>param1 : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>param2 : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>param3 : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>param4 : <span class="params" id="range4_value"></span></span>
        <div><input type="range" class="range" id="range4" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>param5 : <span class="params" id="range5_value"></span></span>
        <div><input type="range" class="range" id="range5" value="300" max="500"></div>
    </div>

    <div class="params_box">
        <span>param6 : <span class="params" id="range6_value"></span></span>
        <div><input type="range" class="range" id="range6" value="200" max="500"></div>
    </div>

</div>

<div class="code_view">
&lt;clipPath id="test_clip_dom1"&gt;<br />
  &lt;path<br />
    id="test_clip_path1"<br />
    d = "<span id="code_view1"></span>"<br />
    rx="150"<br />
    ry="100"<br />
    cx="200"<br />
    cy="120"<br />
    stroke="#999999"<br />
    stroke-width="1"<br />
    fill="#cccccc"<br />
  /&gt;<br />
&lt;/clipPath&gt;<br />
</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
let range5_dom = document.getElementById('range5');
let range6_dom = document.getElementById('range6');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
range5_dom.addEventListener('input', change_range_slider);
range6_dom.addEventListener('input', change_range_slider);

// スライダーを動かした時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);
    console.log("range4_dom.value -> " + range4_dom.value);
    console.log("range5_dom.value -> " + range5_dom.value);
    console.log("range6_dom.value -> " + range6_dom.value);

    // クリップする側の要素を取得する
    let test_clip_path1 = document.getElementById('test_clip_path1');
    console.log("test_clip_path1 -> " + test_clip_path1);

    let d_value = '';
    
    // DOM要素 「id="test_clip_path1" 」の d のパラメータ
    d_value = 'M' + range1_dom.value + ' ' + range2_dom.value
            + ' L' + range3_dom.value + ' ' + range4_dom.value
            + ' L' + range5_dom.value + ' ' + range6_dom.value
            + ' Z';

    // SVG要素の d の値を設定する
    test_clip_path1.setAttribute('d', d_value);

    // パラメータ値を出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');
    let range5_value_dom = document.getElementById('range5_value');
    let range6_value_dom = document.getElementById('range6_value');

    range1_value_dom.innerHTML = range1_dom.value;
    range2_value_dom.innerHTML = range2_dom.value;
    range3_value_dom.innerHTML = range3_dom.value;
    range4_value_dom.innerHTML = range4_dom.value;
    range5_value_dom.innerHTML = range5_dom.value;
    range6_value_dom.innerHTML = range6_dom.value;

    // DOM要素 「id="test_clip_path1" 」の d のパラメータを動的に出力する
    let code_view1_dom = document.getElementById('code_view1');
    code_view1_dom.innerHTML = d_value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、

<clipPath id="test_clip_dom1">
    <path
        id="test_clip_path1"
        d='M16 238 L236 246 L242 22 Z'
        rx="150"
        ry="100"
        cx="200"
        cy="120"
        stroke="#999999"
        stroke-width="1"
        fill="#cccccc"
    />
</clipPath>

のクリップ要素の初期値

d='M16 238 L236 246 L242 22 Z'

が有効になり、三角形のパス要素の中に、
元画像の一部分が見えている状態になります。

また、画面内の6つのパラメータは

d='M16 238 L236 246 L242 22 Z'

のパラメータ内部の値を変更するように作用します。

例えば、パラメータの1から6を

M116 103 L303 10 L251 212 Z

になるように変更すると、画面上では以下の表示になります。

サンプルのHTMLで、パラメータを変更してみると、
クリッピングのパスが元画像にどのように影響しているのかが感覚的につかめますので、
試してみることをお勧めいたします。

クリッピング マスキング について – クリッピングパス

Posted コメントするカテゴリー: javascript

クリッピング マスキング について – クリッピングパス

クリッピングとマスキングについて試してみます。
それぞれの意味は、簡単にいうと

・クリッピング
  内側のものは全て見える
  外側のものは覆い隠す

・マスキング
  グラフィックや他のコンテナ要素を含むコンテナ要素
  前景のオブジェクト(グラフィックや要素)を背景に組成するグラフィック

文字だけを読んで理解するのは直感的ではないので、動作するサンプルで把握してみます。

まず、クリッピングについて試してみます。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
    padding-top: 10px;
    padding-bottom: 2px;
}
.range {
    width: 400px;
}
</style>

</head>
<body>

<svg width="500" height="400" viewBox="0 0 500 400">

    <defs>
        <clipPath id = "test_clip_dom1">
            <ellipse
                rx="150"
                ry="100"
                cx="200"
                cy="120"
                stroke="#999999"
                stroke-width="1"
                fill="#cccccc"
            />
        </clipPath>
    </defs>
    
    <rect
        id="rect_dom"
        x="10"
        y="10"
        cx="10"
        cy="10"
        width="300"
        height="150"
        fill="#999999"
        clip-path="url(#test_clip_dom1)"
    />
    
</svg>

<div>

    <div class="params_box">
        <span>rect x : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>rect y : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>rect cx : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>rect cy : <span class="params" id="range4_value"></span></span>
        <div><input type="range" class="range" id="range4" value="10" max="500"></div>
    </div>

    <div class="params_box">
        <span>rect width : <span class="params" id="range5_value"></span></span>
        <div><input type="range" class="range" id="range5" value="300" max="500"></div>
    </div>

    <div class="params_box">
        <span>rect height : <span class="params" id="range6_value"></span></span>
        <div><input type="range" class="range" id="range6" value="200" max="500"></div>
    </div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
let range5_dom = document.getElementById('range5');
let range6_dom = document.getElementById('range6');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
range5_dom.addEventListener('input', change_range_slider);
range6_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);
    console.log("range4_dom.value -> " + range4_dom.value);
    console.log("range5_dom.value -> " + range5_dom.value);
    console.log("range6_dom.value -> " + range6_dom.value);

    // SVG画像のDOMを取得する
    let rect_dom = document.getElementById('rect_dom');
    console.log("rect_dom -> " + rect_dom);

    // SVG要素を変更する
    rect_dom.setAttribute('x'     , range1_dom.value);
    rect_dom.setAttribute('y'     , range2_dom.value);
    rect_dom.setAttribute('cx'    , range3_dom.value);
    rect_dom.setAttribute('cy'    , range4_dom.value);
    rect_dom.setAttribute('width' , range5_dom.value);
    rect_dom.setAttribute('height', range6_dom.value);
    
    // 画面出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');
    let range5_value_dom = document.getElementById('range5_value');
    let range6_value_dom = document.getElementById('range6_value');

    range1_value_dom.innerHTML = range1_dom.value;
    range2_value_dom.innerHTML = range2_dom.value;
    range3_value_dom.innerHTML = range3_dom.value;
    range4_value_dom.innerHTML = range4_dom.value;
    range5_value_dom.innerHTML = range5_dom.value;
    range6_value_dom.innerHTML = range6_dom.value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、楕円のSVG画像「ellipse」が表示されます。

6つのスライダーは「rect」に対して、パラメータを変更するようになっていて、
スライダーを動かすと楕円がどのようにクリッピングされるかがわかります。

下記のキャプチャはその一例です。

また、クリッピングに使用する「rect」も画面アクセス時には出力されていますが、
「rect」のほうは視覚的に見ることができません。

冒頭でクリッピングの動作について触れましたが、クリッピングは以下の動きをします。

・クリッピング
  内側のものは全て見える
  外側のものは覆い隠す

ここでいう「内側のもの」は「rectで描画されている四角形の内側」という解釈ができます。
また、「外側のものは覆い隠す」については、「rectで描画される四角形の外側」という解釈もできます。

元々の楕円の「ellipse」は常に一定の大きさで描画され、rectでクリッピングされたものが出力されることがわかります。

下記は、スライダー動かし、クリッピングする位置を変更した一例です。

座標変換 transform について – matrix について

Posted コメントするカテゴリー: javascript

座標変換 transform について – matrix について

transform属性の matrix を試してみます。

MDNドキュメントを確認すると、

matrixは、これまでに試してきた「移動」「回転」「縮小」「傾斜」の動作を、2行3列の行列形式で表して定義することができます。

また、2行3列の形ではない変換関数という考え方があり、6つの引数(変換行列)を指定して次のように定義します。

matrix(a, b, c, d, tx, ty)

この変換関数の形で指定した各引数は、以下の3行3列の行列を指定をしたものと同じです。
(上記の説明では2行3列と記載しましたが、変換行列を適用すると3行3列と同様になります)

ここでは、変換関数を使って、SVG画像が画面上でどのように変化するかを把握する、簡単なサンプルを書いて試してみます。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
    padding-top: 10px;
    padding-bottom: 2px;
}
.range {
    width: 400px;
}
.code_view {
    padding: 5px;
    width :400px;
    background-color: #000000;
    color: #ffffff;
}
</style>

</head>
<body>

<svg width="400" height="400" viewBox="100 100 400 400">
    <path
        id           = "test_tran_dom1"
        d            = "M 20 20 A 20 20 0 0 1 100 100"
        stroke       = "#4f4f4f"
        stroke-width = "1"
        fill         = "#cccccc"
        transform    = "matrix(1,0, 0,1, 200,200)"
    />
</svg>

<div class="code_view">
    matrix(
        <span id="code_view1"></span>
        <span id="code_view2"></span>
        <span id="code_view3"></span>
        <span id="code_view4"></span>
        <span id="code_view5"></span>
        <span id="code_view6"></span>
    )
</div>

<div>
    <div class="params_box">
        <span>パラメータa : </span><span class="params" id="range1_value"></span>
        <div><input type="range" class="range" id="range1" value="100" max="360"></div>
    </div>

    <div class="params_box">
        <span>パラメータb : <span class="params" id="range2_value"></span></span>
        <div><input type="range" class="range" id="range2" value="0" max="360"></div>
    </div>

    <div class="params_box">
        <span>パラメータc : <span class="params" id="range3_value"></span></span>
        <div><input type="range" class="range" id="range3" value="0" max="360"></div>
    </div>

    <div class="params_box">
        <span>パラメータd : <span class="params" id="range4_value"></span></span>
        <div><input type="range" class="range" id="range4" value="100" max="360"></div>
    </div>

    <div class="params_box">
        <span>パラメータtx : <span class="params" id="range5_value"></span></span>
        <div><input type="range" class="range" id="range5" value="200" max="400"></div>
    </div>

    <div class="params_box">
        <span>パラメータty : <span class="params" id="range6_value"></span></span>
        <div><input type="range" class="range" id="range6" value="200" max="400"></div>
    </div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
let range5_dom = document.getElementById('range5');
let range6_dom = document.getElementById('range6');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
range5_dom.addEventListener('input', change_range_slider);
range6_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
    console.log("range1_dom.value -> " + range1_dom.value);
    console.log("range2_dom.value -> " + range2_dom.value);
    console.log("range3_dom.value -> " + range3_dom.value);
    console.log("range4_dom.value -> " + range4_dom.value);
    console.log("range5_dom.value -> " + range5_dom.value);
    console.log("range6_dom.value -> " + range6_dom.value);

    // SVG画像のDOMを取得する
    let test_tran_dom1 = document.getElementById('test_tran_dom1');
    console.log("test_tran_dom1 -> " + test_tran_dom1);

    // パラメータの値をリスト(配列)形式にして値を決定する
    let param1_value = (range1_dom.value / 100);
    let param2_value = (range2_dom.value / 100);
    let param3_value = (range3_dom.value / 100);
    let param4_value = (range4_dom.value / 100);
    let param5_value = range5_dom.value;
    let param6_value = range6_dom.value;

    // 各パラメータを引数の形式にまとめる
    let set_param_value = param1_value + ","
                        + param2_value + ","
                        + param3_value + ","
                        + param4_value + ","
                        + param5_value + ","
                        + param6_value;

    // SVG要素の matrix を変更する
    test_tran_dom1.setAttribute('transform', 'matrix(' + set_param_value + ')');
    
    // 画面出力
    let range1_value_dom = document.getElementById('range1_value');
    let range2_value_dom = document.getElementById('range2_value');
    let range3_value_dom = document.getElementById('range3_value');
    let range4_value_dom = document.getElementById('range4_value');
    let range5_value_dom = document.getElementById('range5_value');
    let range6_value_dom = document.getElementById('range6_value');
    range1_value_dom.innerHTML = param1_value;
    range2_value_dom.innerHTML = param2_value;
    range3_value_dom.innerHTML = param3_value;
    range4_value_dom.innerHTML = param4_value;
    range5_value_dom.innerHTML = param5_value;
    range6_value_dom.innerHTML = param6_value;

    let code_view1_dom = document.getElementById('code_view1');
    let code_view2_dom = document.getElementById('code_view2');
    let code_view3_dom = document.getElementById('code_view3');
    let code_view4_dom = document.getElementById('code_view4');
    let code_view5_dom = document.getElementById('code_view5');
    let code_view6_dom = document.getElementById('code_view6');
    code_view1_dom.innerHTML = param1_value + ',';
    code_view2_dom.innerHTML = param2_value + ',';
    code_view3_dom.innerHTML = param3_value + ',';
    code_view4_dom.innerHTML = param4_value + ',';
    code_view5_dom.innerHTML = param5_value + ',';
    code_view6_dom.innerHTML = param6_value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、これまでと同様のサンプルSVG画像が表示されます。

パラメータは a b c d tx ty の6つですが、各値は同じように処理している訳ではなく、

パラメータ 「 a b c d 」 は 100で割って、100分率の値を使用しています。
また、「 tx ty 」 については、座標(SVG画像の位置を決める)を扱うので、スライダーの値をそのまま使用しています。

各パラメータを一つづつ動かしてみると、
a と c は水平方向(x軸方向)に作用し、 b と d は垂直方向(y軸方向)に作用することがわかります。
また、 tx と ty については、SVG画像全体の位置情報(座標)に作業していることがわかります。

座標変換 transform について – skewX skewY について

Posted コメントするカテゴリー: javascript

座標変換 transform について – skewX skewY について

transform属性の skewX を試してみます。
以下のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-bottom: 20px;
}
.range {
	width: 400px;
}
</style>

</head>
<body>

<svg width="400" height="400" viewBox="0 0 400 400">
    <path
        id           = "test_tran_dom1"
        d            = "M 20 20 A 20 20 0 0 1 100 100"
        stroke       = "#4f4f4f"
        stroke-width = "1"
        fill         = "#cccccc"
        transform    = "translate(150, 150)"
    />
</svg>

<div>
	<div class="params_box">
		<span>パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="360"></div>
		<span>skewX : </span>
		<span class="params" id="range1_value"></span>
	</div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);

	// DOMを取得する
	let test_tran_dom1 = document.getElementById('test_tran_dom1');
	console.log("test_tran_dom1 -> " + test_tran_dom1);

	// パラメータの値をリスト(配列)形式にして値を決定する
	let param1_value = range1_dom.value;

	let set_param_value = param1_value;
	console.log("set_param_value -> " + set_param_value);

	// SVG要素の skewX を変更する
	test_tran_dom1.setAttribute('transform', 'translate(150, 150), skewX(' + set_param_value + ')');
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');
	range1_value_dom.innerHTML = set_param_value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、これまでと同様のサンプルSVG画像が表示されます。

スライダーを操作すると、x軸方向に skewX の値が変化し、画像が動的に変わり、画像に対しての効果がわかります。

ちなみに skewX の値を指定している箇所で、下記のように

	// SVG要素の skewX を変更する
	test_tran_dom1.setAttribute('transform', 'translate(150, 150), skewX(' + set_param_value + ')');

同時に「translate(150, 150)」も設定していますが、これはスライダー変更時にSVG画像位置を固定して変化がわかりやすくする為に書いています。
実際の使用シーンでは、座標指定は画面の表示箇所の都合に合わせて指定するとよいと思います。

skewY について

さきほどのサンプルをもとに、transform属性の skewY を試してみます。
以下のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-bottom: 20px;
}
.range {
	width: 400px;
}
</style>

</head>
<body>

<svg width="400" height="400" viewBox="0 0 400 400">
    <path
        id           = "test_tran_dom1"
        d            = "M 20 20 A 20 20 0 0 1 100 100"
        stroke       = "#4f4f4f"
        stroke-width = "1"
        fill         = "#cccccc"
        transform    = "translate(150, 150)"
    />
</svg>

<div>
	<div class="params_box">
		<span>パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="360"></div>
		<span>skewY : </span>
		<span class="params" id="range1_value"></span>
	</div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);

	// DOMを取得する
	let test_tran_dom1 = document.getElementById('test_tran_dom1');
	console.log("test_tran_dom1 -> " + test_tran_dom1);

	// パラメータの値をリスト(配列)形式にして値を決定する
	let param1_value = range1_dom.value;

	let set_param_value = param1_value;
	console.log("set_param_value -> " + set_param_value);

	// SVG要素の skewY を変更する
	test_tran_dom1.setAttribute('transform', 'translate(150, 150), skewY(' + set_param_value + ')');
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');
	range1_value_dom.innerHTML = set_param_value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

画面にアクセスすると、これまでと同様のサンプルSVG画像が表示されます。

スライダーを操作すると、y軸方向に skewY の値が変化し、画像への効果がわかります。

skewX skewY について

さらに、さきほどのサンプルをもとに、transform属性の skewX skewY の併用を試してみます。
以下のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-bottom: 20px;
}
.range {
	width: 400px;
}
</style>

</head>
<body>

<svg width="400" height="400" viewBox="0 0 400 400">
    <path
        id           = "test_tran_dom1"
        d            = "M 20 20 A 20 20 0 0 1 100 100"
        stroke       = "#4f4f4f"
        stroke-width = "1"
        fill         = "#cccccc"
        transform    = "translate(150, 150)"
    />
</svg>

<div>
	<div class="params_box">
		<span>パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="360"></div>
		<span>skewX : </span>
		<span class="params" id="range1_value"></span>
	</div>
	<div class="params_box">
		<span>パラメータ2</span>
		<div><input type="range" class="range" id="range2" value="20" max="360"></div>
		<span>skewY : </span>
		<span class="params" id="range2_value"></span>
	</div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);
	console.log("range2_dom.value -> " + range2_dom.value);

	// DOMを取得する
	let test_tran_dom1 = document.getElementById('test_tran_dom1');
	console.log("test_tran_dom1 -> " + test_tran_dom1);

	// SVG要素の skewX skewY を変更する
	test_tran_dom1.setAttribute('transform', 'translate(150, 150), skewX(' + range1_dom.value + '), skewY(' + range2_dom.value + ')');
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');
	let range2_value_dom = document.getElementById('range2_value');
	range1_value_dom.innerHTML = range1_dom.value;
	range2_value_dom.innerHTML = range2_dom.value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test3.html)

画面にアクセスすると、これまでと同様のサンプルSVG画像が表示されます。

スライダーは2つあり、x方向とy方向の値を変更することができます。
それぞれのスライダーを操作すると、x軸方向に skewX、y軸方向に skewY、の値がそれぞれ変化し、画像への効果がわかります。

skewXを任意の値で変化させた後、skewYを任意の値で変化した場合、両方の効果がSVG画像に適用されることがわかります。

座標変換 transform について – scale について

Posted コメントするカテゴリー: javascript

座標変換 transform について – scale について

transform属性の scale を試してみます。
以下のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-bottom: 20px;
}
.range {
	width: 400px;
}
</style>

</head>
<body>

<svg width="400" height="400" viewBox="0 0 400 400">
    <path
        id           = "test_tran_dom1"
        d            = "M 20 20 A 20 20 0 0 1 100 100"
        stroke       = "#4f4f4f"
        stroke-width = "1"
        fill         = "#cccccc"
        transform    = "translate(10, 10)"
    />
</svg>

<div>
	<div class="params_box">
		<span>パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="300"></div>
		<span>scale(x方向) :</span>
		<span class="params" id="range1_value"></span>
	</div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);

	// DOMを取得する
	let test_tran_dom1 = document.getElementById('test_tran_dom1');

	console.log("test_tran_dom1 -> " + test_tran_dom1);

	// パラメータの値をリスト(配列)形式にして値を決定する
	let param1_value = range1_dom.value;

	let set_param_value = (param1_value / 10);

	console.log("set_param_value -> " + set_param_value);

	// SVG要素の x方向 を変更する
	test_tran_dom1.setAttribute('transform', 'scale(' + set_param_value + ')');
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');

	range1_value_dom.innerHTML = set_param_value + '倍';

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、1つのDOMが出力されます。

パラメータを操作することで、svg画像に指定した x方向の拡大率 の値が変化します。

また、この例では拡大率の変化が把握しやすいように、スライダーの値を10分の1にして適用させています。

座標変換 transform について – scale x方向 y方向 について

先程のサンプルを変更して、y方向にもパラメータを追加してみます。

x方向 y方向 それぞれに scale を適用する場合は、下記の書き方になります。

scale(x, y)

簡単サンプルを書きました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-bottom: 20px;
}
.range {
	width: 400px;
}
</style>

</head>
<body>

<svg width="400" height="400" viewBox="0 0 400 400">
    <path
        id           = "test_tran_dom1"
        x            = "20"
        y            = "20"
        d            = "M 20 20 A 20 20 0 0 1 100 100"
        stroke       = "#4f4f4f"
        stroke-width = "1"
        fill         = "#cccccc"
        transform    = "translate(10, 10)"
    />
</svg>

<div>

	<div class="params_box">
		<span>パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="300"></div>
		<span>scale (x軸方向) :</span>
		<span class="params" id="range1_value"></span>
	</div>

	<div class="params_box">
		<span>パラメータ2</span>
		<div><input type="range" class="range" id="range2" value="20" max="300"></div>
		<span>scale (y軸方向) :</span>
		<span class="params" id="range2_value"></span>
	</div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);
	console.log("range2_dom.value -> " + range2_dom.value);

	// DOMを取得する
	let test_tran_dom1 = document.getElementById('test_tran_dom1');

	console.log("test_tran_dom1 -> " + test_tran_dom1);

	// パラメータの値をリスト(配列)形式にして値を決定する
	let param1_value = (range1_dom.value / 10);
	let param2_value = (range2_dom.value / 10);

	let set_param_value = param1_value + ","
	                    + param2_value;

	console.log("set_param_value -> " + set_param_value);

	// SVG要素の x方向 y方向 を変更する
	test_tran_dom1.setAttribute('transform', 'scale(' + set_param_value + ')');
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');
	let range2_value_dom = document.getElementById('range2_value');

	range1_value_dom.innerHTML = param1_value + '倍';
	range2_value_dom.innerHTML = param2_value + '倍';

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

画面にアクセスすると、一つのSVG画像と、パラメータが2つ表示されます。

x方向のパラメータと、y方向のパラメータを動かすと、それぞれの軸方向に対して、SVG画像が伸縮します。

パラメータが独立しているので、縦横比はバラバラな値が適用されます。
縦横比を維持した形で伸縮する場合は、ロジックを書かなくても y 方向のパラメータを省略するだけで実現可能です。

また、このサンプルも前回同様にスライダーの値を10分の1しています。

座標変換 transform について – rotate について

Posted コメントするカテゴリー: javascript

座標変換 transform について – rotate について

transform属性の rotate を試してみます。
以下のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-bottom: 20px;
}
.range {
	width: 400px;
}
</style>

</head>
<body>

<svg width="400" height="400" viewBox="0 0 400 400">
    <path
        id           = "test_tran_dom1"
        d            = "M 20 20 A 20 20 0 0 1 100 100"
        stroke       = "#4f4f4f"
        stroke-width = "1"
        fill         = "#cccccc"
        transform    = "translate(10, 10)"
    />
</svg>

<div>
	<div class="params_box">
		<span>パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="300"></div>
		<span>rotate :</span>
		<span class="params" id="range1_value"></span>
	</div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);

	// DOMを取得する
	let test_tran_dom1 = document.getElementById('test_tran_dom1');

	console.log("test_tran_dom1 -> " + test_tran_dom1);

	// パラメータの値をリスト(配列)形式にして値を決定する
	let param1_value = range1_dom.value;

	let set_param_value = param1_value;

	console.log("set_param_value -> " + set_param_value);

	// SVG要素の x属性 を変更する
	test_tran_dom1.setAttribute('transform', 'rotate(' + set_param_value + ')');
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');

	range1_value_dom.innerHTML = range1_dom.value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、1つのDOMが出力されます。
パラメータを操作することで、svg画像に指定した rotate の値の変化を見ることができます。

また、このサンプルのrotateは引数が1つだけです。
rotateの引数が1つだけの場合は、SVG画像を描画している要素の「x軸:0 y軸:0」を起点として画像を回転します。

rotate の引数について

rotateの引数を調整することで、回転する起点を変えることができます。

具体的には

rotate(角度, [x方向の起点, y方向の起点])

という形で、引数を割り当てることができます。

例えば

rotate(45, 50, 100)

と指定した場合は、SVG画像を45度回転し、そのSVG画像をx:50、y:100の座標を軸に回転します。

以下、簡単なサンプルを書きました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-bottom: 20px;
}
.range {
	width: 400px;
}
</style>

</head>
<body>

<svg width="400" height="400" viewBox="0 0 400 400">
    <path
        id           = "test_tran_dom1"
        x            = "20"
        y            = "20"
        d            = "M 20 20 A 20 20 0 0 1 100 100"
        stroke       = "#4f4f4f"
        stroke-width = "1"
        fill         = "#cccccc"
        transform    = "translate(10, 10)"
    />
</svg>

<div>

	<div class="params_box">
		<span>パラメータ0</span>
		<div><input type="range" class="range" id="range0" value="20" max="360"></div>
		<span>回転方向 :</span>
		<span class="params" id="range0_value"></span>
	</div>

	<div class="params_box">
		<span>パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="300"></div>
		<span>x軸方向 :</span>
		<span class="params" id="range1_value"></span>
	</div>

	<div class="params_box">
		<span>パラメータ2</span>
		<div><input type="range" class="range" id="range2" value="20" max="300"></div>
		<span>y軸方向 :</span>
		<span class="params" id="range2_value"></span>
	</div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range0_dom = document.getElementById('range0');
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range0_dom.addEventListener('input', change_range_slider);
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range0_dom.value -> " + range0_dom.value);
	console.log("range1_dom.value -> " + range1_dom.value);
	console.log("range2_dom.value -> " + range2_dom.value);

	// DOMを取得する
	let test_tran_dom1 = document.getElementById('test_tran_dom1');

	console.log("test_tran_dom1 -> " + test_tran_dom1);

	// パラメータの値をリスト(配列)形式にして値を決定する
	let param0_value = range0_dom.value;
	let param1_value = range1_dom.value;
	let param2_value = range2_dom.value;

	let set_param_value = param0_value + ","
	                    + param1_value + ","
	                    + param2_value;

	console.log("set_param_value -> " + set_param_value);

	// SVG要素の x属性 を変更する
	test_tran_dom1.setAttribute('transform', 'rotate(' + set_param_value + ')');
	
	// 画面出力
	let range0_value_dom = document.getElementById('range0_value');
	let range1_value_dom = document.getElementById('range1_value');
	let range2_value_dom = document.getElementById('range2_value');

	range0_value_dom.innerHTML = range0_dom.value;
	range1_value_dom.innerHTML = range1_dom.value;
	range2_value_dom.innerHTML = range2_dom.value;

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

画面にアクセスすると、SVG画像と、パラメータが3つ表示されます。

パラメータ0は回転角度、パラメータ1はx座標、パラメータ2はy座標、をそれぞれ変更できます。

例えば、パラメータ1を40、パラメータ2を60にして、パラメータ0の回転角度を変更すると、
rotateは下記のようにセットされ、SVG画像は、x:40 y:60の座標を起点として回転するようになります。

rotate(任意の角度, 40, 60)

パラメータ0~2 をそれぞれ変更すると、引数がどのように影響するか把握しやすくなります。

座標変換 transform について – translate について

Posted コメントするカテゴリー: javascript

座標変換 transform について – translate について

transform属性の translate を試してみます。
以下のサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-bottom: 20px;
}
.range {
	width: 400px;
}
</style>

</head>
<body>

<svg width="400" height="400" viewBox="0 0 400 400">
    <path
        id           = "test_tran_dom1"
        d            = "M 20 20 A 20 20 0 0 1 100 100"
        stroke       = "#4f4f4f"
        stroke-width = "1"
        fill         = "#cccccc"
        transform    = "translate(10, 10)"
    />
</svg>

<div>
	<div class="params_box">
		<span>パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="300"></div>
		<span>x軸方向 :</span>
		<span class="params" id="range1_value"></span>
	</div>

	<div class="params_box">
		<span>パラメータ2</span>
		<div><input type="range" class="range" id="range2" value="20" max="300"></div>
		<span>y軸方向 :</span>
		<span class="params" id="range2_value"></span>
	</div>

</div>

<script>
// スライダの要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);
	console.log("range2_dom.value -> " + range2_dom.value);

	// DOMを取得する
	let test_tran_dom1 = document.getElementById('test_tran_dom1');

	console.log("test_tran_dom1 -> " + test_tran_dom1);

	// パラメータの値をリスト(配列)形式にして値を決定する
	let param1_value = range1_dom.value;
	let param2_value = range2_dom.value;

	let set_param_value = param1_value + ","
	                    + param2_value + " ";

	console.log("set_param_value -> " + set_param_value);

	// SVG要素の x属性 を変更する
	test_tran_dom1.setAttribute('transform', 'translate(' + set_param_value + ')');
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');
	let range2_value_dom = document.getElementById('range2_value');

	range1_value_dom.innerHTML = range1_dom.value + '<br />';
	range2_value_dom.innerHTML = range2_dom.value + '<br />';

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、1つのDOMが出力されます。

また、パラメータが2つあり、それぞれを操作することで、svg画像に指定した translate の値の変化を見ることができます。

座標変換 transform について

Posted コメントするカテゴリー: javascript

座標変換 transform について

transformについて調べてみます。

transformは属性です。
要素を移動、回転、伸縮、傾斜、といった指定で変形します。

属性に対しての指定方法は下記になります。

translate
x方向、y方向に要素を移動する

rotate
指定角度の回転をする

scale
要素を拡大、縮小する

skewX skewY
x方向、y方向に指定した角度分を傾斜する

matrix
2行3列の行列を、変換する関数です。
6個の値を変換行列の形式で変形します。

一つ一つサンプルを書いて確認していきます。

SVGについて – テキストについて(9)

Posted コメントするカテゴリー: javascript

SVGについて – テキストについて(9)

textPath要素について調べてみます。
textPath要素は、textタグのxlink:href属性で、パス情報の定義とidを指定して結び付けます。

以下、サンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-top: 10px;
}

.range {
	width: 300px;
}
</style>

</head>
<body>

<svg width="500" height="250" viewBox="0 0 500 250">

	<path id="test_text1" d="M 20,20 C 40,40 80,40 100,20" stroke="#999999"  fill="transparent"/>
	<text>
		<textPath xlink:href="#test_text1">
			テキストのテストです1
			テキストのテストです2
			テキストのテストです3
			テキストのテストです4
		</textPath>
	</text>

</svg>

<div>
	<div class="params_box">
		<span class="param_title">パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range1_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ2</span>
		<div><input type="range" class="range" id="range2" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range2_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ3</span>
		<div><input type="range" class="range" id="range3" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range3_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ4</span>
		<div><input type="range" class="range" id="range4" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range4_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ5</span>
		<div><input type="range" class="range" id="range5" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range5_value"></span>
	<div>

	<div class="params_box">
		<span class="param_title">パラメータ6</span>
		<div><input type="range" class="range" id="range6" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range6_value"></span>
	<div>

</div>

<script>
// スライダ range1~6 の要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
let range5_dom = document.getElementById('range5');
let range6_dom = document.getElementById('range6');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
range5_dom.addEventListener('input', change_range_slider);
range6_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);
	console.log("range2_dom.value -> " + range2_dom.value);
	console.log("range3_dom.value -> " + range3_dom.value);
	console.log("range4_dom.value -> " + range4_dom.value);
	console.log("range5_dom.value -> " + range5_dom.value);
	console.log("range6_dom.value -> " + range6_dom.value);

	// パターン内のDOM情報を取得する
	let test_text1_dom = document.getElementById('test_text1');

	console.log("test_text1_dom -> " + test_text1_dom);

	// パラメータ1~6まで値をリスト(配列)形式にして値を決定する
	// ただし、値は a,a' b,b' c,c' のようにカンマ区切りで2つセットで決定する
	let param1_value = range1_dom.value;
	let param2_value = range2_dom.value;
	let param3_value = range3_dom.value;
	let param4_value = range4_dom.value;
	let param5_value = range5_dom.value;
	let param6_value = range6_dom.value;

	let set_param_value = param1_value + ","
	                    + param2_value + " "
	                    + param3_value + ","
	                    + param4_value + " "
	                    + param5_value + ","
	                    + param6_value;

	console.log("set_param_value -> " + set_param_value);

	// SVG要素の x属性 を変更する
	test_text1_dom.setAttribute('d', 'M 20,20 C ' + set_param_value);
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');
	let range2_value_dom = document.getElementById('range2_value');
	let range3_value_dom = document.getElementById('range3_value');
	let range4_value_dom = document.getElementById('range4_value');
	let range5_value_dom = document.getElementById('range5_value');
	let range6_value_dom = document.getElementById('range6_value');

	range1_value_dom.innerHTML = range1_dom.value + '<br />';
	range2_value_dom.innerHTML = range2_dom.value + '<br />';
	range3_value_dom.innerHTML = range3_dom.value + '<br />';
	range4_value_dom.innerHTML = range4_dom.value + '<br />';
	range5_value_dom.innerHTML = range5_dom.value + '<br />';
	range6_value_dom.innerHTML = range6_dom.value + '<br />';

}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、「テキストのテスト1テキストのテスト2テキストのテスト3テキストのテスト4」という文字列が出力されますが、パスの定義である

<path id="test_text1" d="M 20,20 C 40,40 80,40 100,20" stroke="#999999"  fill="transparent"/>

に沿った形でテキスト出力されています。

初期値では文字列が「テキストの」までで途切れていますが、画面下のパラメータ1~6を調整することで、
パスの「C」の値を3箇所、動的に変更できます。

パラメータ1から6を変更することで、パスの座標が変化し、パス情報に沿って文字列が出力されることがわかります。

以下、パラメータの設定の一例をキャプチャしたものです。

SVGについて – テキストについて(8)

Posted コメントするカテゴリー: javascript

SVGについて – テキストについて(8)

tspan要素について調べてみます。

tspan要素は、長い文字列の中の一部分の文字列に対してマークアップするシーンで使用します。

text要素の子要素として定義します。
また、tspan要素の中にtspan要素を書いてネストにすることもできます。

以下、サンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<svg width="500" height="200" viewBox="0 0 500 200">

	<text
		x="20"
		y="20"
		dx="0"
		dy="0"
	>
		テキストの
		<tspan x="30" y="80" dx="0" dy="10" fill="#00afff">
			テ
			<tspan dx="5" dy="15" rotate="15" fill="#ff0000">
				ス
			</tspan>
			<tspan dx="25" dy="30" rotate="30">
				ト
			</tspan>
		</tspan>
	</text>

</svg>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、「テキストのテスト」という文字列が「テキストの」までは通常の横書きで出力され、
その後の「テ」「ス」「ト」にはtspanで定義したdx dy rotate fillがそれぞれ個別に影響して出力されていることがわかります。

また、ネストされている要素で、後半の「テスト」全体をfill要素で色の指定をしているので、
親要素の定義が子要素の定義に引き継がれて「テスト」全体が青色に着色されることがわかります。

ただし、2文字目の「ス」は個別にfill要素が定義されているので、その文字だけは赤色になります。
3文字目の「ト」については、親要素のfill属性を引き継いで青色で出力されています。

SVGについて – テキストについて(7)

Posted コメントするカテゴリー: javascript

SVGについて – テキストについて(7)

前々回の x属性の変更のサンプルに対して、writing-mode属性をつけてみます。

writing-mode属性は文字列の出力方向を決定します。

writing-mode="lr"
左から右に出力する(通常の出力と同じ)

writing-mode="rl"
右から左に出力する(通常の出力とは逆になる)

writing-mode="tb"
上から下に出力する(縦書きになる)

具体的なサンプルを用意しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-top: 30px;
}

.range {
	width: 300px;
}
</style>


</head>
<body>

<svg width="500" height="200" viewBox="0 0 500 200">

	<text
		id="test_text1"
		x="20"
		y="20"
		dx="0"
		dy="0"
		transform="rotate(0, 20,40)"
		writing-mode="tb"
	>
	テキストのテスト
	</text>

</svg>


<div>
	<div class="params_box">
		<span class="param_title">パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range1_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ2</span>
		<div><input type="range" class="range" id="range2" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range2_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ3</span>
		<div><input type="range" class="range" id="range3" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range3_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ4</span>
		<div><input type="range" class="range" id="range4" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range4_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ5</span>
		<div><input type="range" class="range" id="range5" value="20" max="400"></div>
		<span>x :</span>
		<span class="params" id="range5_value"></span>
	<div>

</div>


<script>

// スライダ range1 の要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
let range5_dom = document.getElementById('range5');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
range5_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);
	console.log("range2_dom.value -> " + range2_dom.value);
	console.log("range3_dom.value -> " + range3_dom.value);
	console.log("range4_dom.value -> " + range4_dom.value);
	console.log("range5_dom.value -> " + range5_dom.value);

	// パターン内のDOM情報を取得する
	let test_text1_dom = document.getElementById('test_text1');
	let test_text2_dom = document.getElementById('test_text2');
	let test_text3_dom = document.getElementById('test_text3');
	let test_text4_dom = document.getElementById('test_text4');
	let test_text5_dom = document.getElementById('test_text5');

	console.log("test_text1_dom -> " + test_text1_dom);
	console.log("test_text2_dom -> " + test_text2_dom);
	console.log("test_text3_dom -> " + test_text3_dom);
	console.log("test_text4_dom -> " + test_text4_dom);
	console.log("test_text5_dom -> " + test_text5_dom);

	// パラメータ1~パラメータ5まで値をリスト(配列)形式にして角度を決定する
	let param1_value = range1_dom.value;
	let param2_value = range2_dom.value;
	let param3_value = range3_dom.value;
	let param4_value = range4_dom.value;
	let param5_value = range5_dom.value;

	let set_param_value = param1_value + " "
	                    + param2_value + " "
	                    + param3_value + " "
	                    + param4_value + " "
	                    + param5_value;

	console.log("set_param_value -> " + set_param_value);

	// SVG要素の x属性 を変更する
	test_text1_dom.setAttribute('x', set_param_value);
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');
	let range2_value_dom = document.getElementById('range2_value');
	let range3_value_dom = document.getElementById('range3_value');
	let range4_value_dom = document.getElementById('range4_value');
	let range5_value_dom = document.getElementById('range5_value');

	range1_value_dom.innerHTML = range1_dom.value + '<br />';
	range2_value_dom.innerHTML = range2_dom.value + '<br />';
	range3_value_dom.innerHTML = range3_dom.value + '<br />';
	range4_value_dom.innerHTML = range4_dom.value + '<br />';
	range5_value_dom.innerHTML = range5_dom.value + '<br />';

}

</script>


</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、「テキストのテスト」という文字列が縦書きで表示されます。

また、画面下部のパラメータ1~5は、前々回のサンプルのまま設置しています。

縦書きの属性にしても、x方向の各文字の移動はそのまま処理できることがわかります。

SVGについて – テキストについて(6)

Posted コメントするカテゴリー: javascript

SVGについて – テキストについて(6)

テキストの y属性 について試してみます。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-top: 30px;
}

.range {
	width: 300px;
}
</style>


</head>
<body>

<svg width="500" height="200" viewBox="0 0 500 200">

	<text
		id="test_text1"
		x="50"
		y="20"
		dx="0"
		dy="0"
		transform="rotate(0, 20,40)"
	>
	テキストのテスト
	</text>

</svg>


<div>
	<div class="params_box">
		<span class="param_title">パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="20" max="400"></div>
		<span>y :</span>
		<span class="params" id="range1_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ2</span>
		<div><input type="range" class="range" id="range2" value="20" max="400"></div>
		<span>y :</span>
		<span class="params" id="range2_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ3</span>
		<div><input type="range" class="range" id="range3" value="20" max="400"></div>
		<span>y :</span>
		<span class="params" id="range3_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ4</span>
		<div><input type="range" class="range" id="range4" value="20" max="400"></div>
		<span>y :</span>
		<span class="params" id="range4_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ5</span>
		<div><input type="range" class="range" id="range5" value="20" max="400"></div>
		<span>y :</span>
		<span class="params" id="range5_value"></span>
	<div>

</div>


<script>

// スライダ range1 の要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
let range5_dom = document.getElementById('range5');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
range5_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);
	console.log("range2_dom.value -> " + range2_dom.value);
	console.log("range3_dom.value -> " + range3_dom.value);
	console.log("range4_dom.value -> " + range4_dom.value);
	console.log("range5_dom.value -> " + range5_dom.value);

	// パターン内のDOM情報を取得する
	let test_text1_dom = document.getElementById('test_text1');
	let test_text2_dom = document.getElementById('test_text2');
	let test_text3_dom = document.getElementById('test_text3');
	let test_text4_dom = document.getElementById('test_text4');
	let test_text5_dom = document.getElementById('test_text5');

	console.log("test_text1_dom -> " + test_text1_dom);
	console.log("test_text2_dom -> " + test_text2_dom);
	console.log("test_text3_dom -> " + test_text3_dom);
	console.log("test_text4_dom -> " + test_text4_dom);
	console.log("test_text5_dom -> " + test_text5_dom);

	// パラメータ1~パラメータ5まで値をリスト(配列)形式にして角度を決定する
	let param1_value = range1_dom.value;
	let param2_value = range2_dom.value;
	let param3_value = range3_dom.value;
	let param4_value = range4_dom.value;
	let param5_value = range5_dom.value;

	let set_param_value = param1_value + " "
	                    + param2_value + " "
	                    + param3_value + " "
	                    + param4_value + " "
	                    + param5_value;

	console.log("set_param_value -> " + set_param_value);

	// SVG要素の x属性 を変更する
	test_text1_dom.setAttribute('y', set_param_value);
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');
	let range2_value_dom = document.getElementById('range2_value');
	let range3_value_dom = document.getElementById('range3_value');
	let range4_value_dom = document.getElementById('range4_value');
	let range5_value_dom = document.getElementById('range5_value');

	range1_value_dom.innerHTML = range1_dom.value + '<br />';
	range2_value_dom.innerHTML = range2_dom.value + '<br />';
	range3_value_dom.innerHTML = range3_dom.value + '<br />';
	range4_value_dom.innerHTML = range4_dom.value + '<br />';
	range5_value_dom.innerHTML = range5_dom.value + '<br />';

}

</script>


</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、「テキストのテスト」という文字列が表示されます。

前回は、x方向の文字列位置を変更するサンプルでしたが、今回は、y方向に文字列の位置が変化します。

x方向のサンプルと同様に、5つ目のスライダは残り全ての文字列の y座標の位置が変化します。

SVGについて – テキストについて(5)

Posted コメントするカテゴリー: javascript

SVGについて – テキストについて(5)

テキストのx属性 について試してみます。

前回のサンプルをもとに、x 属性の値を可変するサンプルを書きました。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テストHTML</title>

<style>
.params_box {
	padding-top: 30px;
}

.range {
	width: 300px;
}
</style>


</head>
<body>

<svg width="500" height="200" viewBox="0 0 500 200">

	<text
		id="test_text1"
		x="50"
		y="50"
		dx="0"
		dy="0"
		transform="rotate(0, 20,40)"
	>
	テキストのテスト
	</text>

</svg>


<div>
	<div class="params_box">
		<span class="param_title">パラメータ1</span>
		<div><input type="range" class="range" id="range1" value="0" max="400"></div>
		<span>x :</span>
		<span class="params" id="range1_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ2</span>
		<div><input type="range" class="range" id="range2" value="0" max="400"></div>
		<span>x :</span>
		<span class="params" id="range2_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ3</span>
		<div><input type="range" class="range" id="range3" value="0" max="400"></div>
		<span>x :</span>
		<span class="params" id="range3_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ4</span>
		<div><input type="range" class="range" id="range4" value="0" max="400"></div>
		<span>x :</span>
		<span class="params" id="range4_value"></span>
	</div>

	<div class="params_box">
		<span class="param_title">パラメータ5</span>
		<div><input type="range" class="range" id="range5" value="0" max="400"></div>
		<span>x :</span>
		<span class="params" id="range5_value"></span>
	<div>

</div>


<script>

// スライダ range1 の要素を取得し、イベントを付与する
let range1_dom = document.getElementById('range1');
let range2_dom = document.getElementById('range2');
let range3_dom = document.getElementById('range3');
let range4_dom = document.getElementById('range4');
let range5_dom = document.getElementById('range5');

// 各スライダーごとのイベントに、共通の関数を割り当てて処理する
range1_dom.addEventListener('input', change_range_slider);
range2_dom.addEventListener('input', change_range_slider);
range3_dom.addEventListener('input', change_range_slider);
range4_dom.addEventListener('input', change_range_slider);
range5_dom.addEventListener('input', change_range_slider);

// スライダーを動かし時の処理
function change_range_slider()
{
	console.log("range1_dom.value -> " + range1_dom.value);
	console.log("range2_dom.value -> " + range2_dom.value);
	console.log("range3_dom.value -> " + range3_dom.value);
	console.log("range4_dom.value -> " + range4_dom.value);
	console.log("range5_dom.value -> " + range5_dom.value);

	// パターン内のDOM情報を取得する
	let test_text1_dom = document.getElementById('test_text1');
	let test_text2_dom = document.getElementById('test_text2');
	let test_text3_dom = document.getElementById('test_text3');
	let test_text4_dom = document.getElementById('test_text4');
	let test_text5_dom = document.getElementById('test_text5');

	console.log("test_text1_dom -> " + test_text1_dom);
	console.log("test_text2_dom -> " + test_text2_dom);
	console.log("test_text3_dom -> " + test_text3_dom);
	console.log("test_text4_dom -> " + test_text4_dom);
	console.log("test_text5_dom -> " + test_text5_dom);

	// パラメータ1~パラメータ5まで値をリスト(配列)形式にして角度を決定する
	let param1_value = range1_dom.value;
	let param2_value = range2_dom.value;
	let param3_value = range3_dom.value;
	let param4_value = range4_dom.value;
	let param5_value = range5_dom.value;

	let set_param_value = param1_value + " "
	                    + param2_value + " "
	                    + param3_value + " "
	                    + param4_value + " "
	                    + param5_value;

	console.log("set_param_value -> " + set_param_value);

	// SVG要素の x属性 を変更する
	test_text1_dom.setAttribute('x', set_param_value);
	
	// 画面出力
	let range1_value_dom = document.getElementById('range1_value');
	let range2_value_dom = document.getElementById('range2_value');
	let range3_value_dom = document.getElementById('range3_value');
	let range4_value_dom = document.getElementById('range4_value');
	let range5_value_dom = document.getElementById('range5_value');

	range1_value_dom.innerHTML = range1_dom.value + '<br />';
	range2_value_dom.innerHTML = range2_dom.value + '<br />';
	range3_value_dom.innerHTML = range3_dom.value + '<br />';
	range4_value_dom.innerHTML = range4_dom.value + '<br />';
	range5_value_dom.innerHTML = range5_dom.value + '<br />';

}

</script>


</body>
</html>

サーバ上のHTMLはこちら(test1.html)

画面にアクセスすると、「テキストのテスト」という文字列が表示されます。

スライダは全部で5つあり、それぞれのスライダを動かすと、文字列の1~4までは、
スライダの1から4までの値で、x軸の位置が変化し、5つ目のスライダは残り全ての文字列を1つの要素して
x軸方向に位置が変化します。

ここで注意が必要なことは

	test_text1_dom.setAttribute('x', set_param_value);

の箇所で、set_param_value の値をセットしていますが、
この変数の値は、空白で区切られたリスト形式の値をセットしています。

セットする項目は「x」で、1つの項目ですが、セットする値は、単一でも複数(リスト)の値でも動作します。