「小数第1位」まで出力する処理コード

簡略化の基本仕様は小数以下の四捨五入です。 これは小数点の「.」も削除できるので、簡略化の効果が高いからです。 有効数字を減らす、例えば「5691」→「5700」といった操作は、数値の文字数が減らないので逆効果です。

 

一方、手作業の処理で「0.012」「0.208」「0.482」「0.016」などの値が続くと、これらを全て「0」にして良いのか疑問になります。 命令によっては無視できない加工になるのではという気がして来るのです。

 

これまでのコードで、想定以上に悪い結果になるSVGは、普通の四捨五入が荒過ぎる処理なのではと推測しています。 下のSVGは大変に悪い結果が出る例です。

 

 

この改善策に、「小数第2位」以下を四捨五入して「小数第1位」まで出力する処理を試しました。 この処理なら「0.012」「0.208」「0.482」「0.016」は、「0.0」「0.2」「0.5」「0.0」と処理され、それぞれに意味が残ります。 文字数が増える代わりに、画像が良くなるはずです。

 

 

 

処理コード 

「小数第2位」の四捨五入は、元数を10倍して四捨五入し、その結果を10で割る事で可能です。 以下は、四捨五入の肝心の処理部分です。

 

if(count_dot(tmp.join(''))<2){ //「.」が1個以内
    if(count_dot(tmp.join(''))==1){ //「.」が1個(小数)
        tmp_num=parseFloat(tmp.join(''));
        if(f_mode==2 || f_mode==4){ // f_mode値で処理を切替える
            tmp_round=(Math.round(tmp_num*10))/10; }
        else{ // 通常の処理
            tmp_round=Math.round(tmp_num); }}
    else if(count_dot(tmp.join(''))==0){ //「.」が無い(整数)
        tmp_round=parseInt(tmp.join('')); }

    return tmp_round.toString()+i_code[K]; }

else{ //「.」が2個以上
    return tmp.join('')+i_code[K]; }

 

「f_mode」は処理を切替えるための変数です。「F1」「F2」の押下時に「Shift」を押すと、太字のコードが切替って「精密処理」になり、小数第1位までのpathコードが出力される様にしました。

 

 

これは上の様に大変に改善されました。 僅かに黒線が太くなっていますが、言われないと判らない範囲です。 この処理は精密な値の出力なので画像が改善されましたが、簡略化の効果は以下の様にずいぶん劣ります。

 

  元のSVG 761文字
  小数部を四捨五入 496文字
  小数第1位まで出力 686文字

 

元のSVGが上手にコンパクト化されているので、このツールで簡略化する余地が少ないとも言えるでしょう。 無駄の多いSVGコード場合は、もっと効率よく簡略化できると思いますが。

 

しかし、「Shift」を押せば、劣化を抑えた穏やかな簡略化が出来るのは便利です。 この機能はもう少し煮詰めて、簡略化の効率を上げたいと思います。「Simple SVG」の様なツールは、「jpeg」の圧縮と同じで、圧縮方法や圧縮度を調節できて、都合の良い方法を選んで使える様にするのがベストです。

 

 

 

「SVG」の無駄な属性等を削除する 

ネット上で色々なSVG画像のサンプルを入手すると、不要な属性が追加されている場合が多く、これまでは手作業で整形していました。 Adobe Illustratorの出力などは、独自属性が多くて整形が必須ですが、一般に追加される「xmlns属性」も、SVG実装時は不要な事が多いものです。

 

前回に、「F3」押下で「カンマ」→「半角スペース」区切り仕様の変更をワンタッチ化していたので、同時にこの「xmlns属性」を削除できる様にしました。「F3」は、SVGの画質を変えない整形機能という事です。

 

function beautify(Svg_or){
    let title=Svg_or.querySelector('title');
    if(title){
        title.remove(); } // titleタグを削除

    Svg_or.removeAttribute("xmlns"); }

 

上が整形機能の関数ですが、「xmlns」属性と同時に「titleタグ」も削除しています。

また、「<!--  -->」のHTMLコメントのタグが追加される場合も多いので、これは下の関数で削除しています。

 

function clear_comment(){ // コメントタグを削除
    editor_iframe=document.querySelector('.cke_wysiwyg_frame');
    if(editor_iframe){
        iframe_doc=editor_iframe.contentWindow.document;
        if(iframe_doc){
            let iframe_body=iframe_doc.querySelector('.cke_editable');
            if(iframe_body){
                let iframe_node=iframe_body.childNodes;
                for(let k=0; k<iframe_node.length; k++){
                    if(iframe_node[k].nodeType==8){
                        iframe_node[k].remove(); }}
            }}}} // clear_comment()

 

 

 

「Simple SVG」の扱い方 

SVGアイコンを自作するなどの詳しい方法は、前ページに纏めています。

ここは、現在のバージョンの基本的な操作についてのみ書きます。

 

◎ 新しい編集画面を開き、「HTML表示」で「SVG画像」のソースコードをペーストします。 この際、不要な付帯タグなどが削除できるものは、手作業で削除します。

元画像のソースコードを記入するだけで、他の記入はしないのがベストです。

 

◎「通常表示」に戻りSVGコードの整形処理と簡略化処理を行います。

現在利用できる機能は以下です。

 

●「F1」:「半角スペース」区切りのコードの簡略化

●「Shift+F1」:「半角スペース」区切りのコードの簡略化(小数第1位まで出力)

●「F2」:「カンマ」区切りのコードの簡略化

●「Shift+F2」:「カンマ」区切りのコードの簡略化(小数第1位まで出力)

 

●「F3」:  SVGコードの整形処理(一般的な不要タグ・属性などの削除)

 

◎「HTML表示」で処理元のSVG画像のコードを手作業で修正したり、処理元のSVG画像を差替えて、新しいSVG画像を処理することができます。

 

◎「F1」「F2」を押した瞬間に処理が行われます。 処理前と処理後の「SVG画像」が表示されるので、画像の劣化や崩れが無いかなどが判ります。 元の画像は上側に表示され続けますが、「F3」を押すと下側に元画像と同等の画像が表示され、微妙な変化が確認できます。

 

◎「path」コードで、「nnn.nnn.nnn」の様な「数値塊」にドットが2個以上ある場合は、処理をせずそのままの「数値塊」になります。

 

 

 

「Simple SVG」を利用するには 

このツールは Chrome / Edge / Firefox の拡張機能「Tampermonkey」上で動作します。 以下に、このツールの導入手順を簡単に説明します。

 

❶「Tampermonkey」を導入します

使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。 以下のページに簡単な導入の説明があるので参照ください。

 

 

❷「Tampermonkey」にスクリプトを登録します

●「Tampermonkey」の「」マークの「新規スクリプト」タブを開きます。

 

 

 

●「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。

 

〔コピー方法〕 軽量シンプルなツール「PreBox Button   」を使うと

  コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」

  の操作で、掲載コードのコピーが可能になります。

 

● 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。

 

 

〔 Simple SVG 〕 ver. 0.3

 

// ==UserScript==
// @name          Simple SVG ⭐
// @namespace  http://tampermonkey.net/
// @version        0.3
// @description  ブログ編集画面でpathコードを簡略化 実行キー「F1」「F2」「F3」
// @author         Ameba Blog User
// @match         https://blog.ameba.jp/ucs/entry/srventry*
// @exclude       https://blog.ameba.jp/ucs/entry/srventrylist.do*
// @grant          none
// ==/UserScript==


let retry=0;
let interval=setInterval(wait_target, 100);
function wait_target(){
    retry++;
    if(retry>10){ // リトライ制限 10回 1sec
        clearInterval(interval); }
    let target=document.getElementById('cke_1_contents'); // 監視 target
    if(target){
        clearInterval(interval);
        main(); }}


function main(){
    let editor_iframe;
    let iframe_doc;
    let iframe_body;
    let f_mode; // 処理形式

    let target=document.querySelector('#cke_1_contents');
    let monitor=new MutationObserver( catch_key );
    monitor.observe(target, {childList: true});

    catch_key();

    function catch_key(){
        editor_iframe=document.querySelector('.cke_wysiwyg_frame');
        if(editor_iframe){
            iframe_doc=editor_iframe.contentWindow.document;
            if(iframe_doc){

                iframe_doc.addEventListener('keydown', check_key);
                document.addEventListener('keydown', check_key);

                function check_key(event){
                    if(event.keyCode==112){ // ショートカット「F1」
                        event.preventDefault();
                        event.stopImmediatePropagation();
                        f_mode=1;
                        clear_space();
                        svg_arrange(); }

                    if(event.keyCode==112 && event.shiftKey){ //「Shift+F1」
                        event.preventDefault();
                        event.stopImmediatePropagation();
                        f_mode=2;
                        clear_space();
                        svg_arrange(); }

                    if(event.keyCode==113){ // ショートカット「F2」
                        event.preventDefault();
                        event.stopImmediatePropagation();
                        f_mode=3;
                        clear_space();
                        svg_arrange(); }

                    if(event.keyCode==113 && event.shiftKey){ //「Shift+F2」
                        event.preventDefault();
                        event.stopImmediatePropagation();
                        f_mode=4;
                        clear_space();
                        svg_arrange(); }

                   if(event.keyCode==114){ // ショートカット「F3」
                        event.preventDefault();
                        event.stopImmediatePropagation();
                        f_mode=5;
                        clear_space();
                        svg_arrange(); }

                }}}

    } // catch_key()



    function svg_arrange(){
        if(document.querySelector('.cke_wysiwyg_frame') !=null){ //「通常表示」で実行
            editor_iframe=document.querySelector('.cke_wysiwyg_frame');
            iframe_doc=editor_iframe.contentWindow.document;
            if(iframe_doc){
                iframe_body=iframe_doc.querySelector('.cke_editable');
                if(iframe_body){

                    let svg_or;
                    let path_or;
                    let svg_n

                    svg_or=iframe_doc.querySelector('.cke_editable svg');// 処理元のSVG
                    if(svg_or){ // 元のSVG画像が無いと動作しない

                        if(f_mode==5){
                            beautify(svg_or);
                            clear_comment();
                            clear_comment();}


                        let line=iframe_doc.createElement('p');
                        line.id='line';
                        line.textContent=
                            '=========================================';
                        if(!iframe_body.querySelector('#line')){
                            iframe_body.appendChild(line); }

                        svg_n=svg_or.cloneNode(true);

                        let svg_all=iframe_body.querySelectorAll('svg')
                        for(let k=0; k<svg_all.length-1; k++){
                            svg_all[k+1].remove(); } // 最初のSVG以降は削除
                        iframe_body.appendChild(svg_n);

                        path_or=svg_n.querySelectorAll('path'); // 処理元のSVGの全てのpath
                        for(let k=0; k<path_or.length; k++){
                            let d_or=path_or[k].getAttribute("d");
                            path_or[k].setAttribute("d", path_trim(d_or)); }



                        function path_trim(D_or){
                            let d_all=[];
                            if(f_mode==1 || f_mode==2){
                                d_all=D_or.split(' '); }
                            else if(f_mode==3 || f_mode==4 || f_mode==5){
                                d_all=D_or.split(','); }

                            if(f_mode==5){
                                let temp_d;
                                temp_d=d_all.join(' ');
                                return temp_d; } // 処理後のpath出力


                            if(f_mode<5){
                                let temp_d;
                                temp_d=d_all.join(' ');
                                return arrange_i_code(temp_d); }


                            function arrange_i_code(Temp_d){ // path全体の処理
                                let c_count=0; // 数として処理した文字数
                                let i_code=[]; // 全pathを1文字ずつにした配列
                                let i_code_new=[]; // 処理後の数と文字を格納する配列

                                i_code=Temp_d.split(''); // pathの全体を文字1個ずつに分解
                                for(let k=0; k<i_code.length; k++){
                                    if(i_code[k].match(/[A-Za-z]| |-/g)){
                                        if(c_count==0){
                                            i_code_new.push(i_code[k]); }
                                        else{
                                            i_code_new.push(arr_i_code(c_count, k));
                                            c_count=0; }}
                                    else{ // 数字または「.」の場合
                                        c_count+=1; }}

                                return i_code_new.join(''); // 処理後のpath


                                function arr_i_code(Count, K){
                                    let tmp=[];
                                    let tmp_num; // 再構成した数値(小数を含む)
                                    let tmp_round; // 四捨五入した数値
                                    for(let i=0; i<Count; i++){
                                        tmp.push(i_code[K-Count+i]); }

                                    if(count_dot(tmp.join(''))<2){ //「.」が1個以内
                                        if(count_dot(tmp.join(''))==1){
                                            tmp_num=parseFloat(tmp.join(''));
                                            if(f_mode==2 || f_mode==4){
                                                tmp_round=(Math.round(tmp_num*10))/10; }
                                            else{
                                                tmp_round=Math.round(tmp_num); }}
                                        else if(count_dot(tmp.join(''))==0){
                                            tmp_round=parseInt(tmp.join('')); }

                                            return tmp_round.toString()+i_code[K]; }

                                    else{ //「.」が2個以上
                                        return tmp.join('')+i_code[K]; }

                                    function count_dot(str){
                                        let count=0;
                                        for (let i=0; i<str.length; i++){
                                            if(str[i]=="."){
                                                count++; }}
                                        return count; }

                                } // arr_i_code

                            } // arrange_i_code()
                        } // path_trim

                    }}}}} // svg_arrange()



    function beautify(Svg_or){
        let title=Svg_or.querySelector('title');
        if(title){
            title.remove(); } // titleタグを削除

        Svg_or.removeAttribute("xmlns"); }



    function clear_comment(){ // コメントタグを削除
        editor_iframe=document.querySelector('.cke_wysiwyg_frame');
        if(editor_iframe){
            iframe_doc=editor_iframe.contentWindow.document;
            if(iframe_doc){
                let iframe_body=iframe_doc.querySelector('.cke_editable');
                if(iframe_body){
                    let iframe_node=iframe_body.childNodes;
                    for(let k=0; k<iframe_node.length; k++){
                        if(iframe_node[k].nodeType==8){
                             iframe_node[k].remove(); }}
                }}}} // clear_comment()



    function clear_space(){ // svgタグの後に増殖する空白行を削除
        editor_iframe=document.querySelector('.cke_wysiwyg_frame');
        if(editor_iframe){
            iframe_doc=editor_iframe.contentWindow.document;
            if(iframe_doc){
                let iframe_body=iframe_doc.querySelector('.cke_editable');
                if(iframe_body){
                    let elements=iframe_body.querySelectorAll('p');
                    for(let k=0; k<elements.length; k++){
                        if(elements[k].childNodes.length=="1"){
                            if(elements[k].firstElementChild){
                                if(elements[k].firstElementChild.tagName=="BR"){
                                    elements[k].remove(); }}}}
                }}}} // clear_space()

} // main()

// ブログ記事にSVGをHTMLで書き込む
// 通常表示に戻り「F1」または「F2」を押すと、処理したSVGが追加される

 

 

〔参考〕 このページで紹介したSVG画像のソースコードです。「HTML表示」にペーストして表示させて、「Simple SVG」のテストをする事ができます。

 

<svg height="256px" viewbox="0 0 32 32" width="256px">
<style>.cls{fill:#ff005c;}</style>
<path d="M16.86 3.4h-1.6l-.52.71c-.3.43-.73 1-1.22 1.8-2.78 4.21-7.72 12.74-6.23 18.2a6.62 6.62 0 0 0 .43 1.15 5.78 5.78 0 0 0 1 1.45c1.48 1.52 3.86 2.29 7.1 2.29 4.31 0 7.13-1.3 8.41-3.85C27.79 18.1 17.31 4 16.86 3.4Zm5.61 20.86C21.56 26.08 19.33 27 15.85 27a14.58 14.58 0 0 1-1.95-.12 5.65 5.65 0 0 1-4.07-2 2.72 2.72 0 0 1-.32-.51c-1.94-3.88 2-11.62 5.16-16.56.43-.68.84-1.3 1.22-1.85l.17-.24C19.2 10.2 24.73 19.74 22.47 24.26Z"></path><path class="cls" d="M22.47 24.26C21.56 26.08 19.33 27 15.85 27a14.58 14.58 0 0 1-1.95-.12c3.17-.35 5.3-1.61 6.36-3.73 2.32-4.63-1.41-12.31-4.37-17.2l.17-.24C19.2 10.2 24.73 19.74 22.47 24.26Z"></path></svg>

 

 

 

「Simple SVG」最新版について 

旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。

 

●「Simple SVG」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。