<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Frcodewp</title>
	<atom:link href="https://frcodewp.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://frcodewp.com</link>
	<description></description>
	<lastBuildDate>Fri, 08 May 2026 16:40:43 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>Pet Template</title>
		<link>https://frcodewp.com/pet-template/</link>
					<comments>https://frcodewp.com/pet-template/#respond</comments>
		
		<dc:creator><![CDATA[Franknice]]></dc:creator>
		<pubDate>Fri, 08 May 2026 16:40:43 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://frcodewp.com/?p=594</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[  <div id="pcpg-front-wrap">  <div class="pcpg-filter-wrap">  

    <button class="pcpg-filter active" data-type="all">  
        All  
    </button>  

    <button class="pcpg-filter" data-type="dog">  
        Dog  
    </button>  

    <button class="pcpg-filter" data-type="cat">  
        Cat  
    </button>  

</div>  

<div class="pcpg-grid">  

      

        <div class="pcpg-card"  
             data-type="cat"  
             data-bg="https://frcodewp.com/wp-content/uploads/2026/01/grok_image_xvz6g2o.jpg"  
             data-overlay="https://frcodewp.com/wp-content/uploads/2026/05/1778333056949.png"  
             data-overlay-left="0.15480328662849"  
             data-overlay-top="0.0033460675319426"  
             data-overlay-scalex="0.67854490224794"  
             data-overlay-scaley="1.0064764623015"  
             data-overlay-angle="0"  
             data-overlay-canvas-w="1"  
             data-neck-left="0"  
             data-neck-top="0"  
             data-neck-width="0"  
             data-neck-height="0"  
             data-stickers='["https:\/\/frcodewp.com\/wp-content\/uploads\/2026\/02\/Resizer_17723155657663.png"]'>  

            <img decoding="async" src="https://frcodewp.com/wp-content/uploads/2026/01/grok_image_xvz6g2o.jpg">  

            <div class="pcpg-overlay">  
                1  
            </div>  

        </div>  

      

        <div class="pcpg-card"  
             data-type="cat"  
             data-bg="https://frcodewp.com/wp-content/uploads/2026/01/a-photorealistic-studio-photograph-of-a-__DUUEWe5S6KPr4I1Mk0GPQ_KZ4xY3frQrGEqN_ZnImQAw.jpeg"  
             data-overlay="https://frcodewp.com/wp-content/uploads/2026/05/1778333056949.png"  
             data-overlay-left="0.095799386168424"  
             data-overlay-top="0.02482066238537"  
             data-overlay-scalex="0.80884518164795"  
             data-overlay-scaley="0.97612553488445"  
             data-overlay-angle="0"  
             data-overlay-canvas-w="1"  
             data-neck-left="0.39058890000736"  
             data-neck-top="0.14457223564566"  
             data-neck-width="0.2016368557216"  
             data-neck-height="0.12985088119269"  
             data-stickers='["https:\/\/frcodewp.com\/wp-content\/uploads\/2026\/02\/Resizer_17723155657663.png"]'>  

            <img decoding="async" src="https://frcodewp.com/wp-content/uploads/2026/01/a-photorealistic-studio-photograph-of-a-__DUUEWe5S6KPr4I1Mk0GPQ_KZ4xY3frQrGEqN_ZnImQAw.jpeg">  

            <div class="pcpg-overlay">  
                2  
            </div>  

        </div>  

      

</div>

</div>  <!-- EDITOR -->  <div id="pcpg-editor">  <div class="pcpg-editor-inner">  

    <div class="pcpg-canvas-side">  
        <canvas id="pcpg-canvas"></canvas>  
    </div>  

    <div class="pcpg-controls">  

<div class="pcpg-control-group">  
    <label>Upload Pet</label>  

    <input type="file"  
           id="pcpg-upload-head"  
           accept="image/*">  
</div>  

<div class="pcpg-control-group">  
    <label>Sticker</label>  

    <button id="pcpg-add-user-sticker">  
        Add Sticker  
    </button>  
</div>  

<div class="pcpg-control-group">  
    <label>Zoom</label>  

    <input type="range"  
           id="zoom"  
           min="0.1"  
           max="3"  
           step="0.1"  
           value="1">  
</div>  

<div class="pcpg-control-group">  
    <label>Rotate</label>  

    <input type="range"  
           id="rotate"  
           min="0"  
           max="360"  
           value="0">  
</div>  

<div class="pcpg-control-group">  
<label>Flip</label>  
<button id="flip-h">Flip Horizontal</button>

</div>  

<div class="pcpg-control-group">  
    <button id="download">  
        Download PNG  
    </button>  
</div>  

<div class="pcpg-control-group">  
    <button id="close-editor">  
        Close  
    </button>  
</div>

</div>  
</div>  <style>  
  
#pcpg-front-wrap{  
    max-width:1200px;  
    margin:auto;  
    padding:20px;  
}  
  
/*  
=====================================  
FILTERS  
=====================================  
*/  
  
.pcpg-filter-wrap{  
    display:flex;  
    gap:10px;  
    margin-bottom:20px;  
    flex-wrap:wrap;  
}  
  
.pcpg-filter{  
    padding:10px 18px;  
    border:none;  
    border-radius:30px;  
    background:#e5e5e5;  
    color:#000;  
    cursor:pointer;  
    font-weight:700;  
    font-size:14px;  
    line-height:1;  
    transition:0.2s ease;  
}  
  
.pcpg-filter.active{  
    background:#000;  
    color:#fff;  
    box-shadow:0 5px 15px rgba(0,0,0,0.2);  
}  
  
/*  
=====================================  
GRID  
=====================================  
*/  
  
.pcpg-grid{  
    display:grid;  
    grid-template-columns:repeat(auto-fit,minmax(240px,1fr));  
    gap:20px;  
}  
  
.pcpg-card{  
    position:relative;  
    border-radius:24px;  
    overflow:hidden;  
    cursor:pointer;  
    box-shadow:0 10px 30px rgba(0,0,0,0.15);  
}  
  
.pcpg-card img{  
    width:100%;  
    display:block;  
}  
  
.pcpg-overlay{  
    position:absolute;  
    left:0;  
    right:0;  
    bottom:0;  
    padding:18px;  
    background:linear-gradient(transparent, rgba(0,0,0,0.85));  
    color:#fff;  
    font-size:18px;  
    font-weight:700;  
}  
  
/*  
=====================================  
EDITOR  
=====================================  
*/  
  
#pcpg-editor{  
    position:fixed;  
    inset:0;  
    background:rgba(0,0,0,0.96);  
    display:none;  
    z-index:999999;  
    overflow-y:auto;  
    overflow-x:hidden;  
}  
  
.pcpg-editor-inner{  
    width:100%;  
    min-height:100%;  
    display:flex;  
    flex-direction:row;  
    align-items:flex-start;  
    justify-content:center;  
    flex-wrap:nowrap;  
    gap:40px;  
    padding:40px 30px;  
    box-sizing:border-box;  
}  
  
.pcpg-canvas-side{  
    flex:1 1 auto;  
    min-width:0;  
    display:flex;  
    align-items:flex-start;  
    justify-content:flex-end;  
}  
  
.pcpg-canvas-side{  
    flex:1 1 auto;  
    min-width:0;  
}  
  
/*  
=====================================  
CANVAS SIDE  
=====================================  
*/  
  
.canvas-container{  
    border-radius:24px;  
    overflow:hidden;  
    box-shadow:0 10px 40px rgba(0,0,0,0.35);  
}  
  
#pcpg-canvas{  
    display:block;  
}  
  
/*  
=====================================  
CONTROLS  
=====================================  
*/  
  
.pcpg-controls{  
    width:320px;  
    max-width:100%;  
    max-height:85vh;  
  
    overflow-y:auto;  
    overflow-x:hidden;  
  
    background:#fff;  
    border-radius:24px;  
    padding:18px;  
  
    box-sizing:border-box;  
  
    display:flex;  
    flex-direction:column;  
    gap:14px;  
  
    flex-shrink:0;  
  
    margin-left:10px;  
}  
.pcpg-control-group{  
    display:flex;  
    flex-direction:column;  
    gap:8px;  
}  
  
.pcpg-control-group label{  
    font-size:13px;  
    font-weight:700;  
    color:#111;  
    margin:0;  
}  
  
.pcpg-controls input[type="range"]{  
    width:100%;  
    cursor:pointer;  
}  
  
.pcpg-controls input[type="file"]{  
    width:100%;  
    background:#f5f5f5;  
    border:none;  
    padding:10px;  
    border-radius:12px;  
    box-sizing:border-box;  
    font-size:13px;  
}  
  
.pcpg-controls button{  
    width:100%;  
    border:none;  
    background:#000;  
    color:#fff;  
    padding:12px;  
    border-radius:12px;  
    font-weight:700;  
    font-size:14px;  
    cursor:pointer;  
    transition:0.2s ease;  
    line-height:1.2;  
    min-height:auto;  
}  
  
.pcpg-controls button:hover{  
    transform:translateY(-2px);  
}  
  
/*  
=====================================  
SCROLLBAR  
=====================================  
*/  
  
.pcpg-controls::-webkit-scrollbar{  
    width:6px;  
}  
  
.pcpg-controls::-webkit-scrollbar-thumb{  
    background:#ccc;  
    border-radius:20px;  
}  
  
/*  
=====================================  
TABLET  
=====================================  
*/  
  
@media(max-width:1024px){  
  
    .pcpg-editor-inner{  
        flex-direction:column;  
        align-items:center;  
        justify-content:flex-start;  
        padding:30px 15px 60px;  
        gap:30px;  
    }  
  
    .pcpg-canvas-side{  
        width:100%;  
        justify-content:center;  
    }  
  
    .pcpg-controls{  
        width:100%;  
        max-width:700px;  
        max-height:none;  
        overflow:visible;  
    }  
  
}  
  
/*  
=====================================  
MOBILE  
=====================================  
*/  
  
@media(max-width:768px){  
  
    #pcpg-editor{  
        overflow-y:auto;  
    }  
  
    .pcpg-editor-inner{  
        flex-direction:column;  
        align-items:center;  
        justify-content:flex-start;  
        gap:30px;  
        padding:20px 12px 60px;  
        min-height:100%;  
    }  
  
    .pcpg-canvas-side{  
        width:100%;  
        justify-content:center;  
    }  
  
   .canvas-container{  
        max-width:calc(100vw - 24px) !important;  
    }  
  
    #pcpg-canvas{  
        width:100% !important;  
        height:auto !important;  
        border-radius:18px;  
    }  
  
    .pcpg-controls{  
        width:100%;  
        max-width:100%;  
  
        max-height:400px; /* SCROLLABLE */  
        overflow-y:auto;  
  
        border-radius:18px;  
        padding:14px;  
        gap:12px;  
  
        margin-top:10px;  
    }  
  
    .pcpg-filter{  
        padding:7px 12px;  
        font-size:12px;  
    }  
  
    .pcpg-controls button{  
        padding:9px 10px;  
        font-size:12px;  
        border-radius:10px;  
    }  
  
    .pcpg-controls input[type="file"]{  
        padding:8px;  
        font-size:12px;  
    }  
  
    .pcpg-control-group label{  
        font-size:12px;  
    }  
  
    .pcpg-overlay{  
        font-size:15px;  
        padding:12px;  
    }  
  
}  
  
/*  
=====================================  
LARGE DESKTOP  
=====================================  
*/  
  
@media(min-width:1400px){  
  
    #pcpg-canvas{  
        max-height:88vh;  
    }  
  
}  
</style>  <script>  
  
jQuery(function($){  
  
    let canvas = new fabric.Canvas('pcpg-canvas', {  
        preserveObjectStacking:true  
    });  
  
    let activePet = null;

    /* ---- shared layer enforcer ---- */
    function enforceOrder(){
        canvas.getObjects().forEach(function(obj){
            if(obj.isOverlayBack){ canvas.sendToBack(obj); }
        });
        if(activePet){ canvas.bringToFront(activePet); }
        canvas.getObjects().forEach(function(obj){
            if(obj.isOverlay){ canvas.bringToFront(obj); }
        });
        canvas.getObjects().forEach(function(obj){
            if(obj.isSticker){ canvas.bringToFront(obj); }
        });
        canvas.renderAll();
    }  
  
    /*  
    =====================================  
    FILTERS  
    =====================================  
    */  
  
    $('.pcpg-filter').click(function(){  
  
        $('.pcpg-filter').removeClass('active');  
  
        $(this).addClass('active');  
  
        let type = $(this).data('type');  
  
        if(type === 'all'){  
  
            $('.pcpg-card').show();  
  
        } else {  
  
            $('.pcpg-card').hide();  
  
            $('.pcpg-card[data-type="'+type+'"]').show();  
  
        }  
  
    });  
  
    /*  
    =====================================  
    OPEN TEMPLATE  
    =====================================  
    */  
  
    $('.pcpg-card').click(function(){  
  
        canvas.clear();  
  
        let bg = $(this).data('bg');  
  
        let stickers = $(this).data('stickers');  
  
        fabric.Image.fromURL(bg, function(img){  
  
            let maxWidth;  
  
if(window.innerWidth < 768){  
  
    maxWidth = window.innerWidth - 30;  
  
} else if(window.innerWidth < 1200){  
  
    maxWidth = 700;  
  
} else {  
  
    maxWidth = 900;  
  
}  
  
            let ratio = img.height / img.width;  
  
            canvas.setDimensions({  
    width:maxWidth,  
    height:maxWidth * ratio  
});  
  
canvas.calcOffset();  
canvas.renderAll();  
            img.scaleToWidth(maxWidth);  
  
            canvas.setBackgroundImage(  
                img,  
                canvas.renderAll.bind(canvas)  
            );  
  
        });  
  
        /*  
        ==========================  
        TEMPLATE STICKERS  
        ==========================  
        */  
  
        if(stickers){  
  
            stickers.forEach(function(src){  
  
                fabric.Image.fromURL(src, function(sticker){

                    sticker.set({
                        left: 150,
                        top: 150,
                        cornerColor: '#00d4ff',
                        borderColor: '#00d4ff',
                        cornerStyle: 'circle',
                        transparentCorners: false,
                        isSticker: true
                    });

                    sticker.scale(0.3);

                    canvas.add(sticker);
                    enforceOrder();
  
                });  
  
            });  
  
        }  
  
    /*  
        ==========================  
        OVERLAY + NECK LAYER  
        ==========================  
        */  
  
        let overlayUrl    = $(this).data('overlay');  
        let overlayLeft   = parseFloat($(this).data('overlay-left')   || 0);  
        let overlayTop    = parseFloat($(this).data('overlay-top')    || 0);  
        let overlayScaleX = parseFloat($(this).data('overlay-scalex') || 1);  
        let overlayScaleY = parseFloat($(this).data('overlay-scaley') || 1);  
        let overlayAngle  = parseFloat($(this).data('overlay-angle')  || 0);  
  
        /* neck fractions */  
        let neckLeftF   = parseFloat($(this).data('neck-left')   || 0);  
        let neckTopF    = parseFloat($(this).data('neck-top')    || 0);  
        let neckWidthF  = parseFloat($(this).data('neck-width')  || 0);  
        let neckHeightF = parseFloat($(this).data('neck-height') || 0);  
  
        /* store on canvas element for Edit Neck Layer button */  
        canvas._overlayUrl    = overlayUrl;  
        canvas._overlayLeft   = overlayLeft;  
        canvas._overlayTop    = overlayTop;  
        canvas._overlayScaleX = overlayScaleX;  
        canvas._overlayScaleY = overlayScaleY;  
        canvas._overlayAngle  = overlayAngle;  
        canvas._neckLeftF     = neckLeftF;  
        canvas._neckTopF      = neckTopF;  
        canvas._neckWidthF    = neckWidthF;  
        canvas._neckHeightF   = neckHeightF;  
  
        if(overlayUrl){  
  
            /* Load overlay image once, then build two layers from it */  
            fabric.Image.fromURL(overlayUrl, function(overlayImg){  
  
                setTimeout(function(){  
  
                    let fW = canvas.getWidth();  
                    let fH = canvas.getHeight();  
  
                    let oLeft   = overlayLeft   * fW;  
                    let oTop    = overlayTop    * fH;  
                    let oScaleX = (overlayScaleX * fW) / overlayImg.width;  
                    let oScaleY = (overlayScaleY * fH) / overlayImg.height;  
  
                    let hasNeck = neckWidthF > 0 && neckHeightF > 0;  
  
if(hasNeck){

                        /* neck ellipse center and radii in canvas pixels */
                        let neckCX = neckLeftF * fW + (neckWidthF  * fW) / 2;
                        let neckCY = neckTopF  * fH + (neckHeightF * fH) / 2;
                        let neckRX = (neckWidthF  * fW) / 2;
                        let neckRY = (neckHeightF * fH) / 2;

                        /* BACK layer — clipped to show ONLY the neck ellipse area */
                        fabric.Image.fromURL(overlayUrl, function(backImg){

                            /* absolutePositioned:true = canvas coords, no scale math needed */
                            let backClip = new fabric.Ellipse({
                                left:               neckCX,
                                top:                neckCY,
                                rx:                 neckRX,
                                ry:                 neckRY,
                                originX:            'center',
                                originY:            'center',
                                absolutePositioned: true
                                /* NOT inverted — shows only inside the ellipse */
                            });

                            backImg.set({
                                left:         oLeft,
                                top:          oTop,
                                scaleX:       oScaleX,
                                scaleY:       oScaleY,
                                angle:        overlayAngle,
                                clipPath:     backClip,
                                selectable:   false,
                                evented:      false,
                                hoverCursor:  'default',
                                isOverlayBack: true
                            });

                            canvas.add(backImg);
                        enforceOrder();

                    });

                        /* FRONT layer — inverted ellipse = hole at neck position */
                        let frontClip = buildInverseClip(neckCX, neckCY, neckRX, neckRY);

                        overlayImg.set({
                            left:         oLeft,
                            top:          oTop,
                            scaleX:       oScaleX,
                            scaleY:       oScaleY,
                            angle:        overlayAngle,
                            clipPath:     frontClip,
                            selectable:   false,
                            evented:      false,
                            hoverCursor:  'default',
                            isOverlay:    true
                        });

                    } else {  
  
                        /* no neck — single layer as before */  
                        overlayImg.set({  
                            left: oLeft, top: oTop,  
                            scaleX: oScaleX, scaleY: oScaleY,  
                            angle: overlayAngle,  
                            selectable: false, evented: false,  
                            hoverCursor: 'default',  
                            isOverlay: true  
                        });  
                    }  
  
                    canvas.add(overlayImg);
                    enforceOrder();

                }, 100);
  
            });  
        }  
  
        $('#pcpg-editor').fadeIn();  
  
    }); /* end card click */  
  
    /* =========================================================  
       INVERSE CLIP HELPER  
       Returns a clipPath group that shows everything EXCEPT  
       the given rectangle (in image-local coords)  
    ========================================================= */  
  
    /*  
     * buildInverseClip — returns an INVERTED ellipse clipPath.  
     * Fabric renders the image everywhere EXCEPT inside the ellipse.  
     * All coords are in image-local space (pre-divided by scaleX/Y).  
     */  
    /*
     * buildInverseClip
     * Uses absolutePositioned:true so the clip ellipse is in canvas coords,
     * not image-local coords. This means we pass canvas-space coordinates
     * directly — no scale division needed here.
     *
     * neckCX/CY = center of neck ellipse in canvas pixels
     * neckRX/RY = radius of neck ellipse in canvas pixels
     */
    function buildInverseClip(neckCX, neckCY, neckRX, neckRY){

        return new fabric.Ellipse({
            left:               neckCX,
            top:                neckCY,
            rx:                 neckRX,
            ry:                 neckRY,
            originX:            'center',
            originY:            'center',
            absolutePositioned: true,
            inverted:           true
        });
    }
  
    /* =========================================================  
       EDIT NECK LAYER — frontend button  
    ========================================================= */  
  
    let frontNeckRect = null;  
    let frontNeckDrawing = false;  
    let frontNeckStartX = 0, frontNeckStartY = 0;  
  
    $('#pcpg-edit-neck').on('click', function(){  
  
        $('#pcpg-neck-editor-wrap').slideToggle();  
  
        if(frontNeckRect){ canvas.remove(frontNeckRect); frontNeckRect = null; }  
  
        /* show current neck rect */  
        let fW = canvas.getWidth();  
        let fH = canvas.getHeight();  
        let nL = canvas._neckLeftF   * fW;  
        let nT = canvas._neckTopF    * fH;  
        let nW = canvas._neckWidthF  * fW;  
        let nH = canvas._neckHeightF * fH;  
  
       if(nW > 0 && nH > 0){  
            frontNeckRect = new fabric.Ellipse({  
                left:    nL + nW / 2,  
                top:     nT + nH / 2,  
                rx:      nW / 2,  
                ry:      nH / 2,  
                originX: 'center',  
                originY: 'center',  
                fill:    'rgba(0,180,255,0.25)',  
                stroke:  '#00b4ff', strokeWidth:2, strokeDashArray:[6,4],  
                cornerColor:'#00b4ff', borderColor:'#00b4ff',  
                cornerStyle:'circle', transparentCorners:false, cornerSize:10,  
                hasControls:true, hasBorders:true,  
                isFrontNeck:true, selectable:true, evented:true  
            });  
            canvas.add(frontNeckRect);  
            canvas.bringToFront(frontNeckRect);  
            canvas.setActiveObject(frontNeckRect);  
        }  
  
        /* enable drawing if no existing rect */  
        frontNeckDrawing = true;  
        canvas.defaultCursor = 'crosshair';  
        canvas.hoverCursor   = 'crosshair';  
        canvas.selection = false;  
  
        canvas.renderAll();  
    });  
  
    canvas.on('mouse:down', function(o){  
        if(!frontNeckDrawing) return;  
        let p = canvas.getPointer(o.e);  
        frontNeckStartX = p.x; frontNeckStartY = p.y;  
        if(frontNeckRect){ canvas.remove(frontNeckRect); frontNeckRect = null; }  
        frontNeckRect = new fabric.Ellipse({  
            left:    frontNeckStartX,  
            top:     frontNeckStartY,  
            rx:      1, ry:      1,  
            originX: 'left',  
            originY: 'top',  
            fill:    'rgba(0,180,255,0.25)',  
            stroke:  '#00b4ff', strokeWidth:2, strokeDashArray:[6,4],  
            selectable:false, evented:false, isFrontNeck:true  
        });  
        canvas.add(frontNeckRect);  
        canvas.bringToFront(frontNeckRect);  
    });  
  
    canvas.on('mouse:move', function(o){  
        if(!frontNeckDrawing || !frontNeckRect) return;  
        let p    = canvas.getPointer(o.e);  
        let w    = p.x - frontNeckStartX;  
        let h    = p.y - frontNeckStartY;  
        let absW = Math.abs(w);  
        let absH = Math.abs(h);  
        frontNeckRect.set({  
            left: w < 0 ? p.x : frontNeckStartX,  
            top:  h < 0 ? p.y : frontNeckStartY,  
            rx:   absW / 2,  
            ry:   absH / 2  
        });  
        frontNeckRect.setCoords();  
        canvas.renderAll();  
    });  
  
    canvas.on('mouse:up', function(){  
        if(!frontNeckDrawing) return;  
        frontNeckDrawing = false;  
        canvas.selection = true;  
        canvas.defaultCursor = 'default';  
        canvas.hoverCursor   = 'move';  
        if(frontNeckRect){  
            let e  = frontNeckRect;  
            let cX = e.left + e.rx;  
            let cY = e.top  + e.ry;  
            e.set({ left:cX, top:cY, originX:'center', originY:'center',  
                    selectable:true, evented:true, hasControls:true, hasBorders:true });  
            e.setCoords();  
            canvas.setActiveObject(e);  
            canvas.renderAll();  
        }  
    });  
  
    $('#pcpg-neck-done').on('click', function(){  
  
        $('#pcpg-neck-editor-wrap').slideUp();  
  
        /* Read updated neck rect and rebuild overlay layers */  
        let fW = canvas.getWidth();  
        let fH = canvas.getHeight();  
  
        if(frontNeckRect){  
            let e   = frontNeckRect;  
            let rx  = e.rx * (e.scaleX || 1);  
            let ry  = e.ry * (e.scaleY || 1);  
            /* left/top = center because we normalised to center origin on mouse:up */  
            canvas._neckLeftF   = (e.left - rx) / fW;  
            canvas._neckTopF    = (e.top  - ry) / fH;  
            canvas._neckWidthF  = (rx * 2) / fW;  
            canvas._neckHeightF = (ry * 2) / fH;  
            canvas.remove(frontNeckRect);  
            frontNeckRect = null;  
        }  
  
        /* remove old overlay layers and rebuild */  
        canvas.getObjects().slice().forEach(function(obj){  
            if(obj.isOverlay || obj.isOverlayBack){ canvas.remove(obj); }  
        });  
  
        if(canvas._overlayUrl){  
  
            fabric.Image.fromURL(canvas._overlayUrl, function(overlayImg){  
  
                let oLeft   = canvas._overlayLeft   * fW;  
                let oTop    = canvas._overlayTop    * fH;  
                let oScaleX = (canvas._overlayScaleX * fW) / overlayImg.width;  
                let oScaleY = (canvas._overlayScaleY * fH) / overlayImg.height;  
  
                let hasNeck = canvas._neckWidthF > 0 && canvas._neckHeightF > 0;  
  
                if(hasNeck){

                    let neckCX = canvas._neckLeftF * fW + (canvas._neckWidthF  * fW) / 2;
                    let neckCY = canvas._neckTopF  * fH + (canvas._neckHeightF * fH) / 2;
                    let neckRX = (canvas._neckWidthF  * fW) / 2;
                    let neckRY = (canvas._neckHeightF * fH) / 2;

                    fabric.Image.fromURL(canvas._overlayUrl, function(backImg){

                        let backClip = new fabric.Ellipse({
                            left:               neckCX,
                            top:                neckCY,
                            rx:                 neckRX,
                            ry:                 neckRY,
                            originX:            'center',
                            originY:            'center',
                            absolutePositioned: true
                        });

                        backImg.set({
                            left:         oLeft,
                            top:          oTop,
                            scaleX:       oScaleX,
                            scaleY:       oScaleY,
                            angle:        canvas._overlayAngle,
                            clipPath:     backClip,
                            selectable:   false,
                            evented:      false,
                            hoverCursor:  'default',
                            isOverlayBack: true
                        });

                        canvas.add(backImg);
                            enforceOrder();

                        });

                    let frontClip = buildInverseClip(neckCX, neckCY, neckRX, neckRY);
                    overlayImg.set({
                        left:        oLeft,
                        top:         oTop,
                        scaleX:      oScaleX,
                        scaleY:      oScaleY,
                        angle:       canvas._overlayAngle,
                        clipPath:    frontClip,
                        selectable:  false,
                        evented:     false,
                        hoverCursor: 'default',
                        isOverlay:   true
                    });

                } else {
                    overlayImg.set({ left:oLeft, top:oTop, scaleX:oScaleX, scaleY:oScaleY, angle:canvas._overlayAngle, selectable:false, evented:false, hoverCursor:'default', isOverlay:true });  
                }  
  
                canvas.add(overlayImg);
                enforceOrder();

            });  
        }  
    });  
  
    
  
    /*  
    =====================================  
    CLOSE  
    =====================================  
    */  
  
    $('#close-editor').click(function(){  
  
        $('#pcpg-editor').fadeOut();  
  
    });  
  
    /*  
    =====================================  
    UPLOAD PET  
    =====================================  
    */  
  
    $('#pcpg-upload-head').change(function(e){  
  
        let file = e.target.files[0];  
  
        if(!file) return;  
  
        let reader = new FileReader();  
  
        reader.onload = function(event){  
  
            fabric.Image.fromURL(event.target.result, function(img){  
  
                if(activePet){  
  
                    canvas.remove(activePet);  
  
                }  
  
                activePet = img;  
  
                img.set({  
                    left:canvas.width / 2,  
                    top:canvas.height / 2,  
                    originX:'center',  
                    originY:'center',  
                    cornerColor:'#00d4ff',  
                    borderColor:'#00d4ff',  
                    cornerStyle:'circle',  
                    transparentCorners:false  
                });  
  
                img.scale(0.4);  
  
                canvas.add(img);
                canvas.setActiveObject(img);
                enforceOrder();
                 
  
            });  
  
        };  
  
        reader.readAsDataURL(file);  
  
    });  
  
    /*  
    =====================================  
    ADD USER STICKER  
    =====================================  
    */  
  
    $('#pcpg-add-user-sticker').click(function(){  
  
        let input = $('<input type="file" accept="image/*">');  
  
        input.trigger('click');  
  
        input.on('change', function(e){  
  
            let file = e.target.files[0];  
  
            let reader = new FileReader();  
  
            reader.onload = function(event){  
  
                fabric.Image.fromURL(event.target.result, function(img){  
  
                    img.set({  
                        left: 200,  
                        top: 200,  
                        isSticker: true,  
                        cornerColor: '#00d4ff',  
                        borderColor: '#00d4ff',  
                        cornerStyle: 'circle',  
                        transparentCorners: false  
                    });  
  
                    img.scale(0.25);  
  
                    canvas.add(img);
                    enforceOrder();
                    canvas.setActiveObject(img);
                    canvas.renderAll(); 
  
                });  
  
            };  
  
            reader.readAsDataURL(file);  
  
        });  
  
    });  
  
    /*  
    =====================================  
    ZOOM  
    =====================================  
    */  
  
    $('#zoom').on('input', function(){  
  
        let obj = canvas.getActiveObject();  
  
        if(!obj) return;  
  
        obj.scale(parseFloat($(this).val()));  
  
        canvas.renderAll();  
  
    });  
  
    /*  
    =====================================  
    ROTATE  
    =====================================  
    */  
  
    $('#rotate').on('input', function(){  
  
        let obj = canvas.getActiveObject();  
  
        if(!obj) return;  
  
        obj.rotate(parseInt($(this).val()));  
  
        canvas.renderAll();  
  
    });  
  
  
/*  
=====================================  
FLIP HORIZONTAL  
=====================================  
*/  
  
$('#flip-h').click(function(){  
  
    let obj = canvas.getActiveObject();  
  
    if(!obj) return;  
  
    obj.set('flipX', !obj.flipX);  
  
    canvas.renderAll();  
  
});  
  
    /*  
=====================================  
DOWNLOAD  
=====================================  
*/  
  
$('#download').click(function(){  
  
    canvas.discardActiveObject();  
    canvas.renderAll();  
  
    let originalWidth = canvas.getWidth();  
    let originalHeight = canvas.getHeight();  
  
    let dataURL = canvas.toDataURL({  
        format:'png',  
        quality:1,  
        multiplier:5  
    });  
  
    let link = document.createElement('a');  
  
    link.href = dataURL;  
  
    link.download = 'pet-costume.png';  
  
    document.body.appendChild(link);  
  
    link.click();  
  
    document.body.removeChild(link);  
  
    canvas.setWidth(originalWidth);  
    canvas.setHeight(originalHeight);  
  
    canvas.renderAll();  
  
});  
});  
</script>  
]]></content:encoded>
					
					<wfw:commentRss>https://frcodewp.com/pet-template/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
