カテゴリー
【Dart Sass対応】URLエンコード形式のsvg画像でカスタムカーソルを試してみる
※ 当ページには【広告/PR】を含む場合があります。
2020/11/10
まずは注意点
css
url()
svg要素のURLエンコード
url
インラインsvgを準備
ball > billiards
<svg style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#000000" d="M11,13H13V15H11M11,9H13V11H11M11,17H13A2,2 0 0,0 15,15V13.5A1.5,1.5 0 0,0 13.5,12A1.5,1.5 0 0,0 15,10.5V9A2,2 0 0,0 13,7H11A2,2 0 0,0 9,9V10.5A1.5,1.5 0 0,0 10.5,12A1.5,1.5 0 0,0 9,13.5V15A2,2 0 0,0 11,17M12,1C5.92,1 1,5.92 1,12C1,18.08 5.92,23 12,23C18.08,23 23,18.08 23,12C23,5.92 18.08,1 12,1M12,19A7,7 0 0,1 5,12A7,7 0 0,1 12,5A7,7 0 0,1 19,12A7,7 0 0,1 12,19Z" />
</svg>
url
Url-encode
%3Csvg%20style%3D%22width%3A24px%3Bheight%3A24px%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000000%22%20d%3D%22M11%2C13H13V15H11M11%2C9H13V11H11M11%2C17H13A2%2C2%200%200%2C0%2015%2C15V13.5A1.5%2C1.5%200%200%2C0%2013.5%2C12A1.5%2C1.5%200%200%2C0%2015%2C10.5V9A2%2C2%200%200%2C0%2013%2C7H11A2%2C2%200%200%2C0%209%2C9V10.5A1.5%2C1.5%200%200%2C0%2010.5%2C12A1.5%2C1.5%200%200%2C0%209%2C13.5V15A2%2C2%200%200%2C0%2011%2C17M12%2C1C5.92%2C1%201%2C5.92%201%2C12C1%2C18.08%205.92%2C23%2012%2C23C18.08%2C23%2023%2C18.08%2023%2C12C23%2C5.92%2018.08%2C1%2012%2C1M12%2C19A7%2C7%200%200%2C1%205%2C12A7%2C7%200%200%2C1%2012%2C5A7%2C7%200%200%2C1%2019%2C12A7%2C7%200%200%2C1%2012%2C19Z%22%20%2F%3E%0A%3C%2Fsvg%3E
url
url
data:image/svg+xml,
url()
インラインsvgの確認
Take encoded
URLエンコードを行うSass関数の利用
@function _strReplace($substr, $newsubstr, $str, $all:false) {
$pos : str-index($str, $substr);
@while $pos != null {
$strlen : str-length($substr);
$start : str-slice($str, 0, $pos - 1);
$end : str-slice($str, $pos + $strlen);
$str : $start + $newsubstr + $end;
@if $all == true {
$pos : str-index($str, $substr);
} @else {
$pos : null;
}
}
@return $str;
}
@function _svgUrlEncode($svg) {
$repMap : (
"<" : "%3C",
">" : "%3E",
"#" : "%23",
"{" : "%7B",
"}" : "%7D",
"\"" : "'"
);
$enc : $svg;
@each $s, $r in $repMap {
$enc : _strReplace($s, $r, $enc, true);
}
@return $enc;
}
@function svgUrlFunc($svg, $enc:true) {
@if $enc == true {
$svg : _svgUrlEncode($svg);
}
@return url("data:image/svg+xml,#{$svg}");
}
_util.scss
<名前空間>.svgUrlFunc(<引数>)
@use 'util';
///...
cursor: util.svgUrlFunc($svg);
scss部の実装例
$ tree
.
├── my-custom-css-cursor.component.html # メインのhtmlファイル
└── my-custom-css-cursor.component.scss # メインのscssファイル
└ cursor-images
├── _util.scss # 先程のユーティリティ関数
├── _baseball.my-custom-css-cursor.component.scss # 野球のボールのインラインsvg画像を保持したカーソル
├── _billiards.my-custom-css-cursor.component.scss # ビリアードのボールのインラインsvg画像を保持したカーソル
├── _volleyball.my-custom-css-cursor.component.scss # バレーのボールのインラインsvg画像を保持したカーソル
└── _simple.my-custom-css-cursor.component.scss # 丸と四角の図形のインラインsvg画像を保持したカーソル
my-custom-css-cursor.component.html
<div class="custom-cursor-billiards">
<p>Custom Cursor 1 by svg url-encode</p>
</div>
<div class=".custom-cursor-volleyball">
<p>Custom Cursor 2 by svg url-encode</p>
</div>
<div class="custom-cursor-baseball">
<p>Custom Cursor 3 by svg url-encode</p>
</div>
<div class="custom-cursor-img4">
<p>Custom Cursor 4 by svg url-encode</p>
</div>
my-custom-css-cursor.component.scss
@use 'cursor-images/baseball.my-custom-css-cursor.component';
@use 'cursor-images/simple.my-custom-css-cursor.component';
@use 'cursor-images/volleyball.my-custom-css-cursor.component';
@use 'cursor-images/billiards.my-custom-css-cursor.component';
cursor-images
_baseball.my-custom-css-cursor.component.scss
@use 'util';
.custom-cursor-baseball {
$svg: '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#000000" d="M12,2C9.5,2 7.25,2.9 5.5,4.4C6,4.81 6.41,5.27 6.8,5.76L7.89,5.13L8.89,6.87L7.89,7.44C8.45,8.53 8.82,9.73 8.95,11H10V12L10,13H8.95C8.82,14.27 8.45,15.47 7.89,16.56L8.89,17.13L7.89,18.87L6.8,18.24C6.41,18.73 6,19.19 5.5,19.6C7.25,21.1 9.5,22 12,22C14.5,22 16.75,21.1 18.5,19.6C18,19.19 17.59,18.73 17.19,18.24L16.11,18.87L15.11,17.13L16.11,16.55C15.55,15.47 15.18,14.27 15.05,13H14V11H15.05C15.18,9.73 15.55,8.53 16.11,7.45L15.11,6.87L16.11,5.13L17.19,5.76C17.59,5.27 18,4.81 18.5,4.4C16.75,2.9 14.5,2 12,2M4.12,5.85C2.79,7.55 2,9.68 2,12C2,14.32 2.79,16.45 4.12,18.15C4.46,17.87 4.76,17.55 5.05,17.22L4.43,16.87L5.43,15.13L6.16,15.56C6.55,14.77 6.82,13.91 6.93,13H6V12L6,11H6.93C6.82,10.09 6.55,9.23 6.16,8.44L5.43,8.87L4.43,7.13L5.05,6.78C4.76,6.45 4.46,6.13 4.12,5.85M19.88,5.85C19.54,6.13 19.24,6.45 18.95,6.78L19.57,7.13L18.57,8.87L17.84,8.44C17.45,9.23 17.18,10.09 17.07,11H18V13H17.07C17.18,13.91 17.45,14.77 17.84,15.56L18.57,15.13L19.57,16.87L18.95,17.22C19.24,17.55 19.54,17.87 19.88,18.15C21.21,16.45 22,14.32 22,12C22,9.68 21.21,7.55 19.88,5.85Z" /></svg>';
cursor: util.svgUrlFunc($svg), auto;
}
_util.scss
_billiards.my-custom-css-cursor.component.scss
@use 'util';
.custom-cursor-billiards {
$svg: '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#000000" d="M11,13H13V15H11M11,9H13V11H11M11,17H13A2,2 0 0,0 15,15V13.5A1.5,1.5 0 0,0 13.5,12A1.5,1.5 0 0,0 15,10.5V9A2,2 0 0,0 13,7H11A2,2 0 0,0 9,9V10.5A1.5,1.5 0 0,0 10.5,12A1.5,1.5 0 0,0 9,13.5V15A2,2 0 0,0 11,17M12,1C5.92,1 1,5.92 1,12C1,18.08 5.92,23 12,23C18.08,23 23,18.08 23,12C23,5.92 18.08,1 12,1M12,19A7,7 0 0,1 5,12A7,7 0 0,1 12,5A7,7 0 0,1 19,12A7,7 0 0,1 12,19Z" /></svg>';
cursor: util.svgUrlFunc($svg), auto;
}
_volleyball.my-custom-css-cursor.component.scss
@use 'util';
.custom-cursor-volleyball {
$svg: '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#000000" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M13.6,20.35C15.96,18.04 17.69,15.08 18.5,11.76C17.84,11.62 17.18,11.54 16.5,11.5C15.56,15.11 13.41,18.22 10.5,20.37C11,20.45 11.5,20.5 12,20.5C12.55,20.5 13.08,20.45 13.6,20.35M9.23,20.04C12.23,18.07 14.5,15.05 15.46,11.5C14.71,11.55 13.97,11.65 13.27,11.81C12.18,14.89 9.97,17.44 7.13,18.97C7.77,19.42 8.5,19.78 9.23,20.04M20.5,12.37C20.16,12.23 19.81,12.11 19.46,12C18.76,14.9 17.39,17.53 15.54,19.73C18.36,18.44 20.35,15.64 20.5,12.37M3.56,11.04C3.5,11.35 3.5,11.68 3.5,12C3.5,14.5 4.57,16.73 6.27,18.28C6.86,18 7.41,17.66 7.94,17.29C6.08,15.54 4.58,13.41 3.56,11.04M5.33,6.74C4.73,7.5 4.26,8.35 3.95,9.28C4.92,12.13 6.58,14.66 8.74,16.67C9.25,16.24 9.72,15.77 10.15,15.26C7.74,13.03 6,10.08 5.33,6.74M8.04,4.5C7.36,4.85 6.73,5.3 6.18,5.82C6.71,9.21 8.37,12.23 10.77,14.47C11.17,13.91 11.5,13.32 11.82,12.7C9.68,10.56 8.28,7.69 8.04,4.5M19.96,9.03C18.7,8.68 17.37,8.5 16,8.5C14.1,8.5 12.28,8.85 10.61,9.5C10.96,10.1 11.35,10.67 11.8,11.2C13.12,10.75 14.53,10.5 16,10.5C17.57,10.5 19.08,10.78 20.47,11.29C20.4,10.5 20.23,9.74 19.96,9.03M17.54,5.57C17.03,5.5 16.5,5.5 16,5.5C13.69,5.5 11.47,5.94 9.44,6.73C9.62,7.38 9.86,8 10.14,8.61C11.96,7.89 13.93,7.5 16,7.5C17.18,7.5 18.32,7.63 19.42,7.87C18.93,7 18.29,6.21 17.54,5.57M16,4.5C14.79,3.87 13.44,3.5 12,3.5C10.95,3.5 9.94,3.7 9,4.05C9.04,4.63 9.11,5.2 9.21,5.75C11.31,4.95 13.6,4.5 16,4.5Z" /></svg>';
cursor: util.svgUrlFunc($svg) 10 10, auto;
}
_simple.my-custom-css-cursor.component.scss
@use 'util';
.custom-cursor-simple {
$svg: '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 80 80"><g fill="#c44" stroke="#822" stroke-width="2"><circle cx="32" cy="32" r="30" /><rect x="40" y="30" width="80" height="50" /></g></svg>';
cursor: util.svgUrlFunc($svg), auto;
}
完成品
アニメーションを含む動的なインラインsvgを試してみる
url
$ tree
.
├── my-custom-css-cursor.component.html # メインのhtmlファイル
└── my-custom-css-cursor.component.scss # メインのscssファイル
└ cursor-animation
├── _util.scss # 先程のユーティリティ関数
├── _star.my-custom-css-cursor.component.scss # 星をなぞるアニメーション
└── _svg-animation.my-custom-css-cursor.component.scss # 複雑な軌道のアニメーション
<div class="custom-cursor-star">
<p>Custom Cursor 5 by svg url-encode</p>
</div>
<div class="custom-cursor-complex">
<p>Custom Cursor 6 by svg url-encode</p>
</div>
@use 'cursor-animation/star.my-custom-css-cursor.component';
@use 'cursor-animation/svg-animation.my-custom-css-cursor.component';
_star.my-custom-css-cursor.component.scss
@use 'util';
.custom-cursor-star {
$svg: '<svg xmlns="http://www.w3.org/2000/svg" class="svgLineMove" width="80" height="80" viewBox="0, 0, 160, 160"><defs><style>.svgLineMove{stroke-dasharray: 1800;stroke-dashoffset: 0;fill-opacity:1;animation: svgAnime 5s 0s ease-in infinite;} @keyframes svgAnime { 0% {stroke-dashoffset: 1800;fill-opacity:0;} 100% {stroke-dashoffset: 0;fill-opacity:1;}}</style></defs><path d="M75 0 L55 50 L0 50 L40 90 L15 150 L75 115 L135 150 L110 90 L150 50 L95 50 Z" fill="#ffff99" stroke="#ff4d4d" stroke-width="5"></path></svg>';
cursor: util.svgUrlFunc($svg) 40 40, auto;
}
_svg-animation.my-custom-css-cursor.component.scss
@use 'util';
.custom-cursor-complex {
$svg: '<svg xmlns="http://www.w3.org/2000/svg" width="101" height="101" viewBox="0 0 352.74 333"><defs><style>.ellipse {fill:none;stroke-miterlimit:10;stroke-width:5px;opacity:0.6;} .ellipse1 { stroke:aqua;animation: rotation 1.5s ease infinite; transform-origin: center center;} .ellipse2 {stroke:#f6bbff;animation: rotation 1.5s ease infinite;animation-delay: -0.4s;transform-origin: center center;} .ellipse3 {stroke:#fff900;animation: rotation 1.5s ease infinite;animation-delay: -0.8s;transform-origin: center center;}.text {font-size:48px;} .loading-text{fill:#939393; animation: loading-text 2s ease infinite;transform-origin: center center;} .load-complete-text{fill:#727272;display: none;} @keyframes rotation { 0% {transform: scale(0.6) rotate(0deg);} 50% {transform: scale(1.0) rotate(180deg);} 100% {transform: scale(0.6) rotate(360deg);}} @keyframes loading-text { 0%,100% {transform: scale(0.8);opacity: 0;} 50% {transform: scale(1.0);opacity: 1;}}</style></defs><title>Loading</title><ellipse class="ellipse ellipse1" cx="178.74" cy="166.5" rx="146.5" ry="164"/><ellipse class="ellipse ellipse2" cx="178.74" cy="166.5" rx="164" ry="146.5" transform="translate(-59.3 111.68) rotate(-30)"/><ellipse class="ellipse ellipse3" cx="178.74" cy="166.5" rx="146.5" ry="164" transform="translate(-54.82 238.05) rotate(-60)"/><text class="text loading-text" x="89.68" y="178.49">Loading</text><text class="text load-complete-text" transform="translate(0 183.28)">Load Complete!!</text></svg>';
cursor: util.svgUrlFunc($svg) 80 80, auto;
}
ビルド後の表示
まとめ
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー