UNPKG

aico-image-editor

Version:

Combine multiple image into and create single combined image

314 lines (296 loc) 25.4 kB
<div x-data="configurator2d"> <div> <div class="row g-3"> <div class="col-12 col-xxxl-7 d-flex"> <form class="text-center mb-0" enctype="multipart/form-data" :class="$store.canvas.isSaveButtonDisabled ? '':''"> <dropdown-menu datatemplateurl="./dropdownMenu.html" styles="global" shadow="true" x-data="dropdownMenu" class="btn-group btn-group-lg" dropdown-trigger-class="dropdown-toggle-split btn-elegance-primary" data-bs-auto-close="outside" data-bs-strategy="fixed"> <a class="btn btn-lg btn-elegance-primary" type="button" @click="$store.canvas.saveCanvasImage(2000)" :href="$store.canvas.savedImageDownloadUrl" slot="dropdown-append"> <span x-text="getTranslatedHTML('saveText')"></span> </a> <span slot="dropdown-trigger" class="pe-none"> <span class="visually-hidden">Toggle Dropdown</span> </span> <ul slot="dropdown-content" class="list-unstyled" > <div class="form-check form-switch form-check-inline mb-2"> <input class="form-check-input" type="checkbox" value="" id="show-crop" name="show-crop" x-model="$store.canvas.showCropSelectionRect" @change="$store.canvas.toggleCropSelectionRect()"> <label class="form-check-label" for="show-crop" x-text="getTranslatedHTML('crop')"></label> </div> <div class="mb-2" :class="!$store.canvas.showCropSelectionRect ? 'inactiveblock':''"> <div class="d-flex align-items-center mb-1"> <h6 class="mb-0" x-text="getTranslatedHTML('cropCanvas')"></h6> <span class="linedesign ms-3 me-0"></span> </div> <div class="row"> <div class="col-6"> <label class="form-label" for="canvas-width" x-text="getTranslatedHTML('canvasCropWidth')"></label> <input id="canvas-width" type="number" class="form-control form-control-sm border-primary border-2" x-model="$store.canvas.canvasCropWidth" @change="$store.canvas.updateCropSelectionRect()" /> </div> <div class="col-6"> <label class="form-label" for="canvas-height" x-text="getTranslatedHTML('canvasCropHeight')"></label> <input id="canvas-height" type="number" class="form-control form-control-sm border-primary border-2" x-model="$store.canvas.canvasCropHeight" @change="$store.canvas.updateCropSelectionRect()" /> </div> </div> </div> <div> <div class="d-flex align-items-center mb-1"> <h6 class="mb-0" x-text="getTranslatedHTML('imageDimensions')"></h6> <span class="linedesign ms-3 me-0"></span> </div> <div class="row gy-2 mb-3"> <div class="col-6"> <label class="form-label" for="final-image-width" x-text="getTranslatedHTML('finalImageWidth')"></label> <input id="final-image-width" type="number" min="1" :max="$store.canvas.maxCanvasWidth" class="form-control form-control-sm border-primary border-2" x-model="$store.canvas.finalImageWidth" @input="() => { $store.canvas.finalImageWidth = Math.min($store.canvas.finalImageWidth,$el.max) $store.canvas.finalImageWidth = Math.max($store.canvas.finalImageWidth,$el.min) }" /> </div> <div class="col-6"> <label class="form-label" for="final-image-height" x-text="getTranslatedHTML('finalImageHeight')"></label> <input id="final-image-height" type="number" min="1" :max="$store.canvas.maxCanvasHeight" class="form-control form-control-sm border-primary border-2" x-model="$store.canvas.finalImageHeight" @input="() => { $store.canvas.finalImageHeight = Math.min($store.canvas.finalImageHeight,$el.max) $store.canvas.finalImageHeight = Math.max($store.canvas.finalImageHeight,$el.min) }" /> </div> </div> <div class="space-x-2 mb-2"> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" id="scaling-fit" value="fit" x-model="$store.canvas.scalingStretegy" /> <label class="form-check-label" for="scaling-fit" x-text="getTranslatedHTML('fit')"></label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" id="scaling-fill" value="fill" x-model="$store.canvas.scalingStretegy"> <label class="form-check-label" for="scaling-fill" x-text="getTranslatedHTML('fill')"></label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" id="scaling-stretch" value="stretch" x-model="$store.canvas.scalingStretegy"> <label class="form-check-label" for="scaling-stretch" x-text="getTranslatedHTML('stretch')"></label> </div> </div> <div class="mt-3"> <label class="form-label" for="image-size-presets" x-text="getTranslatedHTML('templateImageSIzesLabel')"></label> <select class="form-select form-select-sm border" id="image-size-presets" x-model="presetImageSize" @change="updateFinalImageDim()"> <option value="1080x1920">Instagram Reels - <small>1080 x 1920 px</small></option> <option value="820x312">Facebook Cover Photo - 820 x 312 px</option> <option value="1500x500">Twitter Header Image - 1500 x 500 px</option> <option value="1584x396">LinkedIn Banner Image - 1584 x 396 px</option> <option value="1280x720">YouTube Thumbnail - 1280 x 720 px</option> <option value="1000x1500">Pinterest Pin - 1000 x 1500 px</option> <option value="250x250">Google+ Profile Picture - 250 x 250 px</option> <option value="1080x1920">Snapchat Story - 1080 x 1920 px</option> <option value="1080x1920">TikTok Video - 1080 x 1920 px</option> <option value="1920x1080">Website Hero Image - 1920 x 1080 px</option> </select> </div> <div class="mt-3"> <div class="d-flex align-items-center mb-1"> <h6 class="mb-0">Format</h6> <span class="linedesign ms-3 me-0"></span> </div> <div class="space-x-2"> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" id="format-png" value="png" x-model="$store.canvas.savedImageFormat" /> <label class="form-check-label" for="format-png">png</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" id="format-jpeg" value="jpeg" x-model="$store.canvas.savedImageFormat"> <label class="form-check-label" for="format-jpeg">jpeg</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" id="format-webp" value="webp" x-model="$store.canvas.savedImageFormat"> <label class="form-check-label" for="format-webp">webp</label> </div> </div> </div> <div class="mt-3"> <div class="d-flex align-items-center mb-1"> <h6 class="mb-0" x-text="getTranslatedHTML('quality')"></h6> <info-popover datatemplateurl="./infoPopover.html" styles="global" shadow="true" class="d-inline-block align-middle ms-1" data-bs-trigger="hover focus" data-bs-placement="bottom" x-data="infoPopover"> <span slot="info-popover-trigger" class="cursor-pointer"> <i class="fa-solid fa-circle-info fa-md text-warning lh-1"></i> </span> <div slot="info-popover-content" x-data="localization"> <small x-html="getTranslatedHTML('qualityApply')"></small> </div> </info-popover> <span class="linedesign ms-3 me-0"></span> </div> <div class="row align-items-center" > <div class="col-12" :class="$store.canvas.savedImageFormat === 'png' ? 'inactiveblock':''"> <div class="custom-range-slider"> <input class="w-100 custom-range-slider__control" type="range" id="imageQuality" min="0" max="100" x-model="$store.canvas.savedImageQuality" /> <span class="custom-range-slider__bubble" x-text="$store.canvas.savedImageQuality" :style="{left: setBubblePosition($store.canvas.savedImageQuality, 0, 100)}"></span> </div> </div> <div class="col-12 text-end mt-4 d-flex justify-content-between align-items-center"> <button type="button" class="btn btn-lg btn-primary" @click="$store.canvas.getBundleFileWithSize()"> <span x-text="getTranslatedHTML('calculateImageSize')"></span> <info-popover datatemplateurl="./infoPopover.html" styles="global" shadow="true" class="d-inline-block align-middle ms-1" data-bs-trigger="hover focus" data-bs-placement="bottom" x-data="infoPopover"> <span slot="info-popover-trigger" class="cursor-pointer"> <i class="fa-solid fa-circle-info align-middle fa-md"></i> </span> <div slot="info-popover-content" x-data="localization"> <small x-html="getTranslatedHTML('recalculationInfo')"></small> </div> </info-popover> </button> <span x-show="$store.canvas.savedImageFileSize"> <span x-text="$store.canvas.savedImageFileSize < 1 ? ($store.canvas.savedImageFileSize * 1024).toFixed(2) : $store.canvas.savedImageFileSize.toFixed(2)"></span> <span x-text="$store.canvas.savedImageFileSize < 1 ? 'kb':'mb'"></span> </span> </div> </div> </div> </div> </ul> </dropdown-menu> </form> </div> <div class="col-12 col-xxxl-5 d-flex justify-content-end"> <button type="button" class="btn editor-interface__square me-2 bg-gray" data-bs-toggle="modal" data-bs-target="#aiModal" @click="$store.modal.openModal($store.elements.aiModalEL)"> <span class="nav-tabs-alt-border" x-text="getTranslatedHTML('aiTabTitle')"></span> </button> <button class="btn editor-interface__square bg-gray me-2" data-bs-toggle="tooltip" x-data="tooltip" :title="getTranslatedHTML('crop')" :disabled="$store.canvas.isObjectDeselected || $store.canvas.isTextObjectSelected" @click="$store.canvas.crop($store)"> <i class="fa-solid fa-crop"></i> </button> <button @click="$store.canvas.removeWhiteBtn()" class="btn editor-interface__square bg-gray me-2 d-none" data-bs-toggle="tooltip" x-data="tooltip" :title="getTranslatedHTML('removeWhite')" :disabled="$store.canvas.isObjectFilterControlsDisabled"> <i class="fa-solid fa-circle-minus"></i> </button> <button type="button" class="btn editor-interface__square bg-gray me-2 selected-layer-number flex-shrink-0" data-bs-toggle="tooltip" x-data="tooltip" :title="getTranslatedHTML('layerPositionButtonTitle')" @click="$dispatch('go-to-tab', {tab: 'layer'})" > <span x-text="$store.canvas.selectedObjectLayerIndex"></span> </button> <button type="button" data-bs-toggle="modal" data-bs-target="#objectDeleteConfirmModal" @click="$store.modal.openModal($store.elements.deleteObjectModalEL)" x-data="tooltip" :title="getTranslatedHTML('deleteButtonTitle')" class="btn btn-danger delete-btn editor-interface__square me-2" :disabled="$store.canvas.isObjectDeselected"> <i class="fas fa-lg fa-trash"></i> </button> <button type="button" class="btn editor-interface__square bg-gray me-2" @click="$store.canvas.setObjectFullSize()" :title="getTranslatedHTML('fullSizeButtonText')" x-data="tooltip" data-bs-toggle="tooltip" :disabled="$store.canvas.isObjectDeselected"> <span class="bugano-Icon-awesome-expand-arrows-alt"></span> </button> <button class="btn editor-interface__square bg-gray me-2" :disabled="$store.canvas.zoomCount >= 10" @click="$store.canvas.zoomInCanvas()" x-data="tooltip" data-bs-toggle="tooltip" :title="getTranslatedHTML('zoomInTitle')"> <i class="bugano-zoom-in fa-lg"></i> </button> <button class="btn editor-interface__square bg-gray me-2" :disabled="$store.canvas.zoomCount <= 1" @click="$store.canvas.zoomOutCanvas()" x-data="tooltip" data-bs-toggle="tooltip" :title="getTranslatedHTML('zoomOutTitle')"> <i class="bugano-zoom-out fa-lg"></i> </button> <!-- <button class="btn editor-interface__square bg-gray me-2" @click="$store.canvas.setFullScreenCanvas();"> <i x-show="!$store.canvas.isFullScreen" class="bugano-Icon-awesome-expand-arrows-alt fa-md"></i> <i x-show="$store.canvas.isFullScreen" class="fa-solid fa-compress fa-lg"></i> </button> <button class="btn editor-interface__square bg-gray me-2" @click="$store.canvas.toPDF()"> <i class="fa fa-file-pdf"></i> </button> <button class="btn editor-interface__square bg-gray ms-auto ms-lg-3" @click="$store.canvas.enable3d()"> <span class="fw-bold" >3D</span> </button> --> </div> </div> <div class="my-2 my-lg-0"> <div class="product-canvas-wrapper"> <div class="card"> <div class="card-body"> <div class="row gy-2 mb-3 gx-1"> <div class="col-3"> <label class="form-label" for="canvas-box-width" x-text="getTranslatedHTML('frameWidth')"></label> <input id="canvas-box-width" type="number" min="1" :max="$store.canvas.maxCanvasWidth" class="form-control form-control-sm border-primary border-2" x-model="$store.canvas.canvasWidth" @change="updateCanvasAspectRatio()"/> </div> <div class="col-3"> <label class="form-label" for="canvas-box-height" x-text="getTranslatedHTML('frameHeight')"></label> <input id="canvas-box-height" type="number" min="1" :max="$store.canvas.maxCanvasHeight" class="form-control form-control-sm border-primary border-2" x-model="$store.canvas.canvasHeight" @change="updateCanvasAspectRatio()" /> </div> <div class="col"> <label class="form-label" x-text="getTranslatedHTML('sizeTemplateSaveLabel')"></label> <div class="input-group input-group-sm mb-2"> <input class="form-control form-control-sm border-primary border-2" type="text" id="current-size-preset-label" x-model="currentSizePresetLabel" :placeholder="getTranslatedHTML('templateName')" autocomplete="off"/> <button type="button" class="btn btn-sm btn-primary" x-text="getTranslatedHTML('addTitle')" @click="addSizeToTemplate()"></button> </div> </div> </div> <div class="row gy-2 mb-3 gx-1"> <div class="col-auto"> <div class="form-check form-switch form-check-inline"> <input class="form-check-input" type="checkbox" value="" id="workspace-template" name="workspace-template" x-model="isWorkspaceTemplate" /> <label class="form-check-label" for="workspace-template" x-text="getTranslatedHTML('globalTemplate')"></label> </div> </div> <div class="col" x-show="$store.canvas.sizeTemplates.length || $store.canvas.sizeTemplatesForWorkspace.length"> <label class="form-label" x-text="getTranslatedHTML('templateSelectionDropdownLabel')"></label> <select class="form-select form-select-sm border" id="image-size-presets" x-model="presetCanvasDim" @canvas-reset.window="clearSizeTemplates()" @change="updateCanvasDim()" @canvas-data-restored.window="() => { populateSizeTemplates($event.detail.sizeTemplates) }" @canvas-is-ready.window.once="getSizeTemplateForWorkspace()"> <template x-if="$store.canvas.sizeTemplates.length"> <option value="" disabled x-text="getTranslatedHTML('savedPresets')"></option> </template> <template x-for="sizeTemplate in $store.canvas.sizeTemplates"> <option :value="`${sizeTemplate.width}x${sizeTemplate.height}`" x-text="`${sizeTemplate.label} - ${sizeTemplate.width} x ${sizeTemplate.height} px`"></option> </template> <template x-if="$store.canvas.sizeTemplatesForWorkspace.length"> <option value="" disabled x-text="getTranslatedHTML('globalPresets')"></option> </template> <template x-for="sizeTemplateForWorkspace in $store.canvas.sizeTemplatesForWorkspace"> <option :value="`${sizeTemplateForWorkspace.width}x${sizeTemplateForWorkspace.height}`" x-text="`${sizeTemplateForWorkspace.label} - ${sizeTemplateForWorkspace.width} x ${sizeTemplateForWorkspace.height} px`"></option> </template> </select> </div> </div> </div> </div> <div class="ratio ratio-1x1"> <div id="product-canvas-holder" class="d-flex justify-content-center align-items-center"> <canvas id="product-canvas" x-init="() => { $store.elements.canvasEL = $el; }"></canvas> <!-- now this will be not needed as background color is replaced by background image--> <!-- <img :src="$store.canvas.getSelectedProductObj().productImageUrl" class="img-fluid product-canvas-img" alt="" /> --> </div> </div> <div class="my-3 text-center"> <button type="button" class="btn editor-interface__square bg-gray me-2 historybackbtn" data-bs-toggle="tooltip" x-data="tooltip" :title="getTranslatedHTML('undoTitle')" x-init="() => { $store.elements.historyUndo = $el; }" @click="canvasHistory.back()"> <i class="fa-solid fa-arrow-rotate-left"></i> </button> <button type="button" class="btn editor-interface__square bg-gray me-2 historyforwardbtn" data-bs-toggle="tooltip" x-data="tooltip" :title="getTranslatedHTML('redoTitle')" x-init ="() => { $store.elements.historyRedo = $el; $store.canvas.disableUndoRedoButtons(); }" @click="canvasHistory.forward()" > <i class="fa-solid fa-arrow-rotate-right"></i> </button> </div> </div> </div> </div> </div>