質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.06%

マスクさせるレイヤーを指定したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 591

score 13

使用したjsテンプレートを改造しています
data-mklineは元々黒色をマスクするものですが、マスク指定カラーを白に変え、
キャンバス全体をマスクではなく一つのレイヤー(mklayer="8")を指定してマスクさせたいのですが
コードをどう変えてもわからず理解不能に陥っています

Maker = function(){

    //■処理 //

    /**
        @brief アイコン画像を更新する。
    */
    this.updateResultImage = function() //
    {
        this.resultContext.clearRect( 0 , 0 , this.resultCanvas.width , this.resultCanvas.height );

        for( var $i = 0 ; this.maxLayer >= $i ; ++$i ) //全てのレイヤーを処理
        {
            var $image = document.querySelector( '[data-mklayer="' + $i + '"][data-mkselect]' );

            if( $image ) //選択されている素材がある場合
            {
                if( $image.getAttribute( 'data-mkclip' ) )
                    { this.clipImage( $image ); }
                else if( $image.getAttribute( 'data-mkcolor' ) )
                    { this.drawColorImage( $image ); }
                else
                    { this.drawImage( $image ); }
            }
        }

        this.resultImage.setAttribute( 'src' , this.resultCanvas.toDataURL() );
    }

    /**
        @brief 指定の画像を内部キャンバスに描画する。
    */
    this.drawImage = function( $iImage ) //
    {
        this.workContext.clearRect( 0 , 0 , this.workCanvas.width , this.workCanvas.height );
        this.workContext.drawImage( $iImage , 0 , 0 , this.workCanvas.width , this.workCanvas.height );

        var $image = this.workContext.getImageData( 0 , 0 , this.workCanvas.width , this.workCanvas.height );

        for( var $i = 0 ; $image.data.length > $i ; $i += 4 ) //全てのピクセルを処理
        {
            $image.data[ $i ]     = this.lineColor.red   * ( 255 - $image.data[ $i ] )     + this.fillColor.red   * $image.data[ $i ];
            $image.data[ $i + 1 ] = this.lineColor.green * ( 255 - $image.data[ $i + 1 ] ) + this.fillColor.green * $image.data[ $i + 1 ];
            $image.data[ $i + 2 ] = this.lineColor.blue  * ( 255 - $image.data[ $i + 2 ] ) + this.fillColor.blue  * $image.data[ $i + 2 ];
        }

        this.workContext.putImageData( $image , 0 , 0 );
        this.resultContext.drawImage( this.workCanvas , 0 , 0 , this.resultCanvas.width , this.resultCanvas.height );
    }

    /**
        @brief 指定の画像を色を変更せずに内部キャンバスに描画する。
    */
    this.drawColorImage = function( $iImage ) //
        { this.resultContext.drawImage( $iImage , 0 , 0 , this.resultCanvas.width , this.resultCanvas.height ); }

    /**
        @brief 指定の画像を使って内部キャンバスをマスクする。
    */
    this.clipImage = function( $iImage ) //
    {
        this.workContext.clearRect( 0 , 0 , this.workCanvas.width , this.workCanvas.height );
        this.workContext.drawImage( $iImage , 0 , 0 , this.workCanvas.width , this.workCanvas.height );

        var $workImage   = this.workContext.getImageData( 0 , 0 , this.workCanvas.width , this.workCanvas.height );
        var $resultImage = this.resultContext.getImageData( 0 , 0 , this.resultCanvas.width , this.resultCanvas.height );

        for( var $i = 0 ; $resultImage.data.length > $i ; $i += 4 ) //全てのピクセルを処理
        {
            $resultImage.data[ $i + 3 ] = ( $resultImage.data[ $i + 3 ] - $workImage.data[ $i + 3 ] );
            $workImage.data[ $i + 3 ]   = ( 255 * 3 - $workImage.data[ $i ] - $workImage.data[ $i + 1 ] - $workImage.data[ $i + 2 ] ) / 3 * $workImage.data[ $i + 3 ] / 255;

            $workImage.data[ $i ]     = this.lineColor.red   * 255;
            $workImage.data[ $i + 1 ] = this.lineColor.green * 255;
            $workImage.data[ $i + 2 ] = this.lineColor.blue  * 255;
        }

        this.resultContext.putImageData( $resultImage , 0 , 0 );
        this.workContext.putImageData( $workImage , 0 , 0 );
        this.resultContext.drawImage( this.workCanvas , 0 , 0 , this.resultCanvas.width , this.resultCanvas.height );
    }

    /**
        @brief 指定の画像を選択状態にする。
    */
    this.selectImage = function( $iImage ) //
    {
        var $layer = $iImage.getAttribute( 'data-mklayer' );
        var $image = document.querySelector( '[data-mklayer="' + $layer + '"][data-mkselect]' );

        $image.setAttribute( 'class' , $image.getAttribute( 'class' ).replace( 'mkselect' , '' ) );
        $image.removeAttribute( 'data-mkselect' );
        $iImage.setAttribute( 'class' , $iImage.getAttribute( 'class' ) + ' mkselect' );
        $iImage.setAttribute( 'data-mkselect' , true );
    }

    /**
        @brief 指定の色を使用する。
    */
    this.selectColor = function( $iColor )
    {
        var $lineColor = $iColor.getAttribute( 'data-mkline' );
        var $fillColor = $iColor.getAttribute( 'data-mkfill' );

        if( $lineColor ) //ラインの色指定がある場合
        {
            var $color = $lineColor.split( ',' );

            this.lineColor.red   = parseFloat( $color[ 0 ] );
            this.lineColor.green = parseFloat( $color[ 1 ] );
            this.lineColor.blue  = parseFloat( $color[ 2 ] );

            var $current = document.querySelector( '[data-mkline][data-mkselect]' );

            $current.setAttribute( 'class' , $current.getAttribute( 'class' ).replace( 'mkselect' , '' ) );
            $current.removeAttribute( 'data-mkselect' );
            $iColor.setAttribute( 'class' , $iColor.getAttribute( 'class' ) + ' mkselect' );
            $iColor.setAttribute( 'data-mkselect' , true );
        }

        if( $fillColor ) //塗りつぶしの色指定がある場合
        {
            var $color = $fillColor.split( ',' );

            this.fillColor.red   = parseFloat( $color[ 0 ] );
            this.fillColor.green = parseFloat( $color[ 1 ] );
            this.fillColor.blue  = parseFloat( $color[ 2 ] );

            var $current = document.querySelector( '[data-mkfill][data-mkselect]' );

            $current.setAttribute( 'class' , $current.getAttribute( 'class' ).replace( 'mkselect' , '' ) );
            $current.removeAttribute( 'data-mkselect' );
            $iColor.setAttribute( 'class' , $iColor.getAttribute( 'class' ) + ' mkselect' );
            $iColor.setAttribute( 'data-mkselect' , true );
        }
    }

    //■初期化 //

    this.resultImage   = document.querySelector( 'IMG[data-mkresult]' );
    this.layerImage    = document.querySelectorAll( 'IMG[data-mklayer]' );
    this.lineColors    = document.querySelectorAll( '[data-mkline]' );
    this.fillColors    = document.querySelectorAll( '[data-mkfill]' );
    this.resultCanvas  = document.createElement( 'canvas' );
    this.resultContext = this.resultCanvas.getContext( '2d' );
    this.workCanvas    = document.createElement( 'canvas' );
    this.workContext   = this.workCanvas.getContext( '2d' );
    this.lineColor     = { 'red' : 0 , 'green' : 0 , 'blue' : 0 };
    this.fillColor     = { 'red' : 1 , 'green' : 1 , 'blue' : 1 };
    this.maxLayer      = 0;

    if( !this.resultImage ) //出力先のIMGタグを絞り込めない場合
        { throw 'アイコンの出力先を設定できません。「data-mkresult」属性を持つIMGタグをページ内のどこかに"1つだけ"記述してください。'; }

    if( !this.layerImage.length ) //素材のIMGタグが見つからない場合
        { throw 'アイコン素材が1つもありません。「data-mklayer」属性を持つIMGタグをページ内のどこかに記述してください。'; }

    this.resultCanvas.width  = this.resultImage.getAttribute( 'width' );
    this.resultCanvas.height = this.resultImage.getAttribute( 'height' );
    this.workCanvas.width    = this.resultImage.getAttribute( 'width' );
    this.workCanvas.height   = this.resultImage.getAttribute( 'height' );

    var $maker = this;

    for( var $i = 0 ; this.layerImage.length > $i ; ++$i ) //全てのアイコン素材を処理
    {
        var $image = this.layerImage[ $i ];

        $image.addEventListener( 'click'     , function(){ $maker.selectImage( this ); $maker.updateResultImage(); } );
        $image.addEventListener( 'mouseover' , function(){ addTooltip( this ); } );
        $image.addEventListener( 'mouseout'  , function(){ deleteTooltip( this ); } );

        if( $image.getAttribute( 'data-mkselect' ) ) //初期選択値の場合
            { this.selectImage( $image ); }

        if( this.maxLayer < $image.getAttribute( 'data-mklayer' ) ) //現在のレイヤーカウントより大きい場合
            { this.maxLayer = $image.getAttribute( 'data-mklayer' ); }
    }

    for( var $i = 0 ; this.lineColors.length > $i ; ++$i ) //全てのライン色を処理
    {
        var $color = this.lineColors[ $i ];

        $color.addEventListener( 'click' , function(){ $maker.selectColor( this ); $maker.updateResultImage(); } );

        if( $color.getAttribute( 'data-mkselect' ) ) //初期選択値の場合
            { this.selectColor( $color ); }
    }

    for( var $i = 0 ; this.fillColors.length > $i ; ++$i ) //全ての塗りつぶし色を処理
    {
        var $color = this.fillColors[ $i ];

        $color.addEventListener( 'click' , function(){ $maker.selectColor( this ); $maker.updateResultImage(); } );

        if( $color.getAttribute( 'data-mkselect' ) ) //初期選択値の場合
            { this.selectColor( $color ); }
    }

    this.updateResultImage();
};

function addTooltip( $iImage )
    {
        var $span      = document.createElement( 'span' );
        var $innerSpan = document.createElement( 'span' );

        $span.setAttribute( 'class' , 'mktooltipcontainer' );
        $innerSpan.setAttribute( 'class' , 'mktooltip' );
        $innerSpan.innerText = $iImage.getAttribute( 'alt' );

        $span.appendChild( $innerSpan );
        $iImage.parentNode.insertBefore( $span , $iImage );
    }

function deleteTooltip( $iImage )
    { document.querySelector( '.mktooltip' ).parentNode.removeChild( document.querySelector( '.mktooltip' ) ); }

//★処理 //

window.addEventListener( 'load' , function(){ new Maker(); } );


マスクした白色を変えるHTML

<span class="border block" style="background-color:#799ea6" data-mkfill="0.475, 0.620, 0.651">&nbsp;</span>


指定させたいレイヤーのHTMLの一部

data-mklayer="8" data-mkcolor="true"
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

もうあきらめたのでいいです

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る