首页 > 解决方案 > Livewire 和用于缩放图像的内联 js 脚本存在问题

问题描述

卡在这里2天了,请指教。

我有这个 Livewire ProductDetail 模态,它显示 Livewirepublic $show = true和我有一个侦听器监听viewProduct事件的时间,当收到事件时viewProduct调用公共方法并将产品分配给public $product然后$this->show = !this->show,模态按预期显示。

问题是我在刀片文件中有一个 js 脚本,当你用鼠标悬停时,它在产品图像上实现了缩放功能,这一切都搞砸了。

我尝试了使用 Livewire 事件和 Alpine js 的不同方法,但仍然没有运气。

Livewire ProductDetail Component

<?php

namespace App\Http\Livewire;

use App\Models\Product;
use App\Updatable;
use Livewire\Component;

class ProductDetail extends Component
{
    use Updatable;

    public $show = false;

    // public $product;

    protected $listeners = ['viewProduct', 'cartUpdated' => '$refresh'];

    public function viewProduct(Product $product)
    {
        $this->product = $product;

        $this->show = !$this->show;
    }

    public function render()
    {
        return view('livewire.product-detail');
    }
}

产品细节.blade.php

@php
    $cartContent = Cart::content();
@endphp
<div wire:igone x-data="{
    
    show: @entangle('show'),

}" x-show="show" x-cloak class="bg-black bg-opacity-50 fixed inset-0 lg:flex lg:items-center overflow-scroll z-10">
    @if (isset($product))
        <div class="bg-white lg:max-w-screen-md lg:min-h-0 min-h-screen mx-auto relative w-full xl:max-w-screen-lg rounded-md overflow-hidden">
            <div class="lg:flex lg:gap-6 py-6 px-4">
                

                <div class="w-1/2 flex items-center justify-center">
                   
                    <x-image-zoom :image="$product->image" />
                   
                </div>

                <div class="flex-1 mt-2">
                    <div class="flex flex-col justify-between">
                        <h1 class="flex-1 text-2xl mt-1 max-w-xs leading-none">
                            {{ $product->name }}
                        </h1>

                        <div class="flex justify-start my-4">
                            <x-badge class="text-xl" :product="$product" />
                        </div>

                        <div>
                            <p>{{ $product->unit_size }}</p>

                            <div class="flex items-center justify-start space-x-2 mt-3 leading-none">
                                <div class="font-semibold inline-flex items-baseline text-gray-700">
                                    <span class="text-gray-500 pr-1">Ks</span>
                                    <span class="text-2xl" x-text="getFormattedPrice('{{ $product->discount_available }}', '{{ $product->discount }}', '{{ $product->price }}')" />
                                </div>

                                <div x-show="ifDiscountAvailable('{{ $product->discount_available }}')">
                                    <span class="line-through tracking-tight text-gray-500 font-semibold">{{ $product->formatted_price }}</span>
                                </div>
                            </div>
                        </div>

                        <p class="text-sm text-gray-600 my-8">
                            {{  $product->description  }}
                        </p>
                    </div>
                </div>
            </div>

            <div class="bg-gray-200 h-32 px-3 py-3">
                Footer
            </div>
        </div>
    @endif
</div>

问题组件请看一下这个并提出建议

<x-image-zoom :image="$product->image" />传递图像的路径

<div>
    <div
        x-data="initiate()"
        x-on:mouseenter="zoomImage('myimage', 'myresult')"
        x-on:mouseleave="removeCreatedElements()"
        class="img-zoom-container w-full h-full relative">
        <img id="myimage" src="{{ asset('storage/'.$image) }}">
        <div id="myresult" class="img-zoom-result"></div>
    </div>
</div>
<script>
    function initiate() {
        return {
            zoomImage(imgID, resultID) {
                var img, lens, result, cx, cy;
                img = document.getElementById(imgID);
                result = document.getElementById(resultID);
                result.setAttribute('class', 'absolute inset-0');
                
                lens = document.createElement("DIV");
                lens.setAttribute("class", "absolute border-2 border-accent w-52 h-52");
                lens.setAttribute('id', 'zoomLense');
                
                img.parentElement.insertBefore(lens, img);
                
                cx = result.offsetWidth / lens.offsetWidth;
                cy = result.offsetHeight / lens.offsetHeight;
                
                result.style.backgroundImage = "url('" + img.src + "')";
                result.style.backgroundSize = (img.width * cx) + "px " + (img.height * cy) + "px";
                
                lens.addEventListener("mousemove", moveLens);
                img.addEventListener("mousemove", moveLens);
                result.addEventListener("mousemove", moveLens);
                
                lens.addEventListener("touchmove", moveLens);
                img.addEventListener("touchmove", moveLens);
                result.addEventListener("touchmove", moveLens);
                
        function moveLens(e) {
                    var pos, x, y;
                    
                    e.preventDefault();
                    
                    pos = getCursorPos(e);
                    
                    x = pos.x - (lens.offsetWidth / 2);
                    y = pos.y - (lens.offsetHeight / 2);
                    
        
                    if (x > img.width - lens.offsetWidth) { x = img.width - lens.offsetWidth; }
                    if (x < 0) { x = 0; }
                    if (y > img.height - lens.offsetHeight) { y = img.height - lens.offsetHeight; }
                    if (y < 0) { y = 0; }
                
            /*set the position of the lens:*/
                    lens.style.left = x + "px";
                    lens.style.top = y + "px";
                    
            /*display what the lens "sees":*/
                    result.style.backgroundPosition = "-" + (x * cx) + "px -" + (y * cy) + "px";
                }

                function getCursorPos(e) {
                    var a, x = 0, y = 0;
                    e = e || window.event;

                    /*get the x and y positions of the image:*/
                    a = img.getBoundingClientRect();

                    /*calculate the cursor's x and y coordinates, relative to the image:*/
                    x = e.pageX - a.left;
                    y = e.pageY - a.top;

                    /*consider any page scrolling:*/
                    x = x - window.pageXOffset;
                    y = y - window.pageYOffset;
                    return { x: x, y: y };
                }
            },

            removeCreatedElements() {
                document.getElementById('zoomLense').remove();
                document.getElementById('myresult').style.backgroundImage = 'none';
            }
        }
    }
</script>

如果我执行以下操作,则上述脚本有效,ProductDetail.php但是当产品更改时,js 会变得混乱

<?php

namespace App\Http\Livewire;

use App\Models\Product;
use App\Updatable;
use Livewire\Component;

class ProductDetail extends Component
{
    use Updatable;

    public $show = false;

    // public $product;

    protected $listeners = ['viewProduct', 'cartUpdated' => '$refresh'];

    public function viewProduct(Product $product)
    {
        // $this->product = $product;

        $this->show = !$this->show;
    }
    public function render()
    {
        // return view('livewire.product-detail');
        return view('livewire.product-detail', ['product' => Product::find(1)]);
    }
}

标签: javascriptlaravel-livewirezooming

解决方案


推荐阅读