Chcę mieć możliwość powiększenia punktu znajdującego się pod myszą na płótnie HTML 5, tak jak w Mapach Google . Jak mogę to osiągnąć?
javascript
html
canvas
csiz
źródło
źródło
Odpowiedzi:
Lepszym rozwiązaniem jest po prostu przesunięcie pozycji rzutni na podstawie zmiany powiększenia. Punkt powiększenia to po prostu punkt w starym powiększeniu i nowym powiększeniu, który ma pozostać taki sam. To znaczy, że rzutnia powiększona wstępnie i rzutnia powiększona po powiększeniu mają ten sam punkt powiększenia w stosunku do rzutni. Biorąc pod uwagę, że skalujemy się w stosunku do pochodzenia. Możesz odpowiednio dostosować położenie rzutni:
Tak naprawdę możesz po prostu przesuwać w dół iw prawo podczas powiększania, o współczynnik powiększenia, w stosunku do punktu, w którym powiększyłeś.
źródło
Wreszcie rozwiązałem to:
Kluczem, jak wskazał @Tatarize , jest obliczenie pozycji osi w taki sposób, aby punkt powiększenia (wskaźnik myszy) pozostał w tym samym miejscu po powiększeniu.
Oryginalnie mysz jest w pewnej odległości
mouse/scale
od rogu, chcemy, aby punkt pod myszą pozostał w tym samym miejscu po powiększeniu, ale jest to zmouse/new_scale
dala od rogu. Dlatego musimy przesunąćorigin
(współrzędne narożnika), aby to uwzględnić.Pozostały kod musi następnie zastosować skalowanie i przetłumaczyć na kontekst rysowania, aby jego początek pokrywał się z rogiem płótna.
źródło
W rzeczywistości jest to bardzo trudny problem (matematycznie) i pracuję prawie nad tym samym. Zadałem podobne pytanie na Stackoverflow, ale nie otrzymałem odpowiedzi, ale wysłałem je w DocType (StackOverflow dla HTML / CSS) i otrzymałem odpowiedź. Sprawdź to http://doctype.com/javascript-image-zoom-css3-transforms-calculate-origin-example
Jestem w trakcie tworzenia wtyczki jQuery, która to robi (zoom w stylu Google Maps przy użyciu transformacji CSS3). Mam trochę powiększenie do kursora myszy, ale wciąż próbuję wymyślić, jak pozwolić użytkownikowi przeciągać płótno, tak jak można to zrobić w Mapach Google. Kiedy zacznę działać, wyślę tutaj kod, ale sprawdź powyższy link, aby uzyskać część dotyczącą powiększania myszą do punktu.
Nie zdawałem sobie sprawy, że istnieją metody skalowania i tłumaczenia w kontekście Canvas, możesz osiągnąć to samo używając CSS3 np. przy użyciu jQuery:
Upewnij się, że ustawiłeś początek transformacji CSS3 na 0, 0 (-moz-transform-origin: 0 0). Korzystanie z transformacji CSS3 umożliwia powiększanie wszystkiego, po prostu upewnij się, że kontener DIV jest ustawiony na przepełnienie: ukryty, aby powiększone krawędzie nie wysypywały się z boków.
Niezależnie od tego, czy używasz transformacji CSS3, czy własnych metod skalowania i translacji kanwy, zależy od Ciebie, ale sprawdź powyższe łącze, aby uzyskać obliczenia.
Aktualizacja: Meh! Po prostu opublikuję kod tutaj, zamiast skłaniać Cię do podążania za linkiem:
Będziesz oczywiście musiał dostosować go do użycia skali płótna i metod tłumaczenia.
Aktualizacja 2: Właśnie zauważyłem, że używam transform-origin razem z translate. Udało mi się zaimplementować wersję, która po prostu używa skali i samodzielnie tłumaczy, sprawdź to tutaj http://www.dominicpettifer.co.uk/Files/Mosaic/MosaicTest.html Poczekaj na pobranie obrazów, a następnie użyj kółko myszy do powiększania, obsługuje również przesuwanie przez przeciąganie obrazu. Używa transformacji CSS3, ale powinieneś być w stanie użyć tych samych obliczeń dla swojego płótna.
źródło
Natknąłem się na ten problem przy użyciu c ++, którego prawdopodobnie nie powinienem był po prostu użyć macierzy OpenGL na początek ... w każdym razie, jeśli używasz kontrolki, której źródłem jest lewy górny róg i chcesz przesuwać / powiększać podobnie jak mapy google, oto układ (używając allegro jako mojej obsługi zdarzeń):
źródło
Podoba mi się odpowiedź Tatarize , ale podam alternatywę. Jest to trywialny problem z algebry liniowej, a metoda, którą przedstawiam, działa dobrze z panoramowaniem, powiększaniem, pochylaniem itp. Oznacza to, że działa dobrze, jeśli obraz jest już przekształcony.
Gdy macierz jest skalowana, skala znajduje się w punkcie (0, 0). Tak więc, jeśli masz obraz i przeskalujesz go 2-krotnie, prawy dolny punkt podwoi się w obu kierunkach (zgodnie z konwencją, że [0, 0] to lewy górny róg obrazu).
Jeśli zamiast tego chcesz powiększyć obraz wokół środka, rozwiązanie jest następujące: (1) przesuń obraz tak, aby jego środek znajdował się w punkcie (0, 0); (2) przeskaluj obraz za pomocą współczynników x i y; (3) przetłumaczyć obraz z powrotem. to znaczy
Mówiąc bardziej abstrakcyjnie, ta sama strategia działa w każdym punkcie. Jeśli na przykład chcesz przeskalować obraz w punkcie P:
I wreszcie, jeśli obraz jest już w jakiś sposób przekształcony (na przykład, jeśli jest obrócony, pochylony, przesunięty lub przeskalowany), to bieżąca transformacja musi zostać zachowana. W szczególności transformacja zdefiniowana powyżej musi zostać pomnożona post (lub pomnożona w prawo) przez transformację prądową.
Masz to. Oto plunk, który pokazuje to w akcji. Przewiń kółkiem myszy na kropkach, a zobaczysz, że konsekwentnie pozostają na miejscu. (Testowane tylko w Chrome). Http://plnkr.co/edit/3aqsWHPLlSXJ9JCcJzgH?p=preview
źródło
Oto moje rozwiązanie dla obrazu zorientowanego na środek:
źródło
Oto alternatywny sposób na zrobienie tego, który używa setTransform () zamiast scale () i translate (). Wszystko jest przechowywane w tym samym obiekcie. Zakłada się, że płótno znajduje się w punkcie 0,0 na stronie, w przeciwnym razie będziesz musiał odjąć jego pozycję od współrzędnych strony.
Towarzyszący kod do obsługi panoramowania:
Aby samodzielnie uzyskać odpowiedź, weź pod uwagę, że te same współrzędne strony muszą odpowiadać tym samym współrzędnym kanwy przed i po powiększeniu. Następnie możesz wykonać algebrę, zaczynając od tego równania:
(pageCoords - tłumaczenie) / scale = canvasCoords
źródło
Chcę tu zamieścić kilka informacji dla tych, którzy wykonują oddzielnie rysowanie obrazu i przenoszenie - powiększanie go.
Może to być przydatne, gdy chcesz przechowywać powiększenia i położenie rzutni.
Oto szuflada:
Uwaga: skala MUSI być pierwsza .
A oto zoomer:
i oczywiście potrzebowalibyśmy dragger:
źródło
źródło
Oto implementacja kodu odpowiedzi @ tatarize przy użyciu PIXI.js. Mam okno robocze, które patrzy na część bardzo dużego obrazu (np. W stylu Google Maps).
$canvasContainer
jest moim kontenerem html.imageContainer
to mój kontener PIXI, w którym znajduje się obraz.mousePosOnImage
to pozycja myszy względem całego obrazu (nie tylko portu widoku).Oto jak uzyskałem pozycję myszy:
źródło
Musisz uzyskać punkt w przestrzeni świata (w przeciwieństwie do przestrzeni ekranu) przed i po powiększeniu, a następnie przetłumaczyć przez deltę.
Pozycja myszy jest w przestrzeni ekranu, więc musisz ją przekształcić w przestrzeń świata. Proste przekształcenie powinno wyglądać podobnie do tego:
źródło
możesz użyć funkcji scrollto (x, y), aby obsłużyć położenie paska przewijania w prawo do punktu, który ma zostać pokazany po powiększeniu. do znalezienia pozycji myszy użyj event.clientX i event.clientY. to ci pomoże
źródło
Jedna ważna rzecz ... jeśli masz coś takiego:
Musisz zrobić coś równoważnego w płótnie:
źródło