Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Kreslení na canvas po zadání hodnot z inputu.

Aktivity
Avatar
Jan Novák
Člen
Avatar
Jan Novák:18.1.2022 19:30

Zdravím, lámu si hlavu s nejspíše naprosto primitivní chybou, ale nejsem schopen na ni přijít.

Zkusil jsem:

function getMousePos(event)
{
   return {
    x: event.offsetX,
    y: event.offsetY
  };
}

var canvas = document.getElementById('myCanvas');
var kontext = canvas.getContext('2d');

function draw()
{
  var souradnice1 = Number(document.getElementById("souradnice1").value);
  var souradnice2 = Number(document.getElementById("souradnice2").value);

canvas.addEventListener('click', function(event)
  {
  console.log(document.getElementById("souradnice1").value);
  console.log(document.getElementById("souradnice2").value);
  let mousePos = getMousePos(event);
  kontext.strokeStyle = "red";
  kontext.beginPath();
  kontext.moveTo(mousePos.x,mousePos.y);
  kontext.lineTo(mousePos.x+souradnice1,mousePos.y+souradnice2);
  kontext.closePath();
  kontext.stroke();
  },false);
}

Zde na příkladu uvádím jádro problému. Zadám pomocí inputu dvě hodnoty a stisknutím tlačítka tyto dvě hodnoty uložím do souradnice1 a souradnice2. Následně pak kliknutím na canvas vygeneruju čáru, jak lze vidět v kódu. Po prvním vložení hodnot je ještě vše v pořádku. Ale po opakovaném zadávání a následném vykreslování čáry na canvas se vykreslí i čáry z předešlými hodnotami. Já samozřejmě potřebuji aby se při každém zadání hodnot generovala jen jedna čára odpovídající hodnotám. Děkuji moc za rady! Zde můžete zkusit https://jsfiddle.net/knb56rq1/

 
Odpovědět
18.1.2022 19:30
Avatar
JsonKody
Člen
Avatar
JsonKody:18.1.2022 23:36

Nevim jestli to chapu spravne -> ty souradnice dole jsou jeden bod, a cara se ma kreslit z nej tam kam klikas? Takze to udela takovyho jezka casem?

Opravil jsem trochu ten kod. Mimochodem mas tam jeden velky nesmysl a to ze po kazdem zmacknuti tlacitka (onclick) zavolas funkci 'draw' a ta prida novy event listener. Ten stary event listener ale stale posloucha ;)

https://codepen.io/…/pen/qBPwJzd?…

 
Nahoru Odpovědět
18.1.2022 23:36
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:19.1.2022 8:13

Jo, presne, tez na to koukam, co je to za nesmysl....
"po kazdem zmacknuti tlacitka (onclick) zavolas funkci 'draw'"

V prvni rade bych to prepsal takto. Protoze evidentne nevis, co delas, tak bych nespojoval zapisy funkci do vice urovni a vsechny funkce dal k sobe, prehledne. Jestli to funguje, nevim. Jen jsem to preskladal.

function getMousePos(event)
{
   return {
    x: event.offsetX,
    y: event.offsetY
  };
}

function draw(event) // tady jsem doplnil event
{
  var souradnice1 = Number(document.getElementById("souradnice1").value);
  var souradnice2 = Number(document.getElementById("souradnice2").value);
// tady jsem ty kody spojil. Mozna, ze jsi to tak chtel udelat, ale mel jsi to napsane jinak
  console.log(souradnice1);
  console.log(souradnice2);
  var mousePos = getMousePos(event); // proc mas "var souradnice1" ale "let mousePos", bud pouzivej "var" nebo "let"
  kontext.strokeStyle = "red";
  kontext.beginPath();
  kontext.moveTo(mousePos.x, mousePos.y);
  kontext.lineTo(mousePos.x + souradnice1, mousePos.y + souradnice2); // neboj se pouzivat mezery
  kontext.closePath();
  kontext.stroke();
}

// --- inicializace ---
var canvas = document.getElementById('myCanvas');
var kontext = canvas.getContext('2d');
canvas.addEventListener('click', draw, false); // take by melo fungovat: canvas.onclick = draw;
// eventy prirazujes jen 1x, obvykle
 
Nahoru Odpovědět
19.1.2022 8:13
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:19.1.2022 8:40

Na tom js-fiddle mi to ne uplne spravne zjistuje souradnice. Tak mozna pogooblovat a najit reseni, ktere cte souradnice spravne.

<canvas id=myCanvas style="width:200px; height:200px; border:2px solid #f00"></canvas>
<div>
    <input type="text" id="souradnice1"> <br>
    <input type="text" id="souradnice2"> <br>
    <button id="butt">Generuj</button> <br>
  </div>
<script>
  function getMousePos(event)
{
   return {
      x: event.clientX - event.target.offsetLeft,
      y: event.clientY - event.target.offsetTop
 };

}

function getInput(event)
{
  souradnice1 = Number(document.getElementById("souradnice1").value);
  souradnice2 = Number(document.getElementById("souradnice2").value);
}

function draw(event)
{
  console.log(souradnice1);
  console.log(souradnice2);
  var mousePos = getMousePos(event);
  kontext.strokeStyle = "red";
  kontext.beginPath();
  kontext.moveTo(mousePos.x, mousePos.y);
  kontext.lineTo(mousePos.x + souradnice1, mousePos.y + souradnice2); // neboj se pouzivat mezery
  kontext.closePath();
  kontext.stroke();
}

// --- inicializace ---
var butt = document.getElementById('butt');
var canvas = document.getElementById('myCanvas');
var kontext = canvas.getContext('2d');
  var souradnice1; // musis je pridat global, pokud je chces pouzivat ve dvou ruznych funkcich
  var souradnice2;
canvas.addEventListener('click', draw, false);
butt.addEventListener('click', getInput, false);
</script>
Editováno 19.1.2022 8:40
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
19.1.2022 8:40
Avatar
Jan Novák
Člen
Avatar
Odpovídá na Peter Mlich
Jan Novák:19.1.2022 9:27

Moc děkuji. A ano, nebyl jsem si přesně jistý co dělám a ano vyleze z toho někdy neprostý nesmysl.... :) Učím se to sám a jsem teprve víceméně v začátcích, takže to často funguje na bázi pokusu a omylu... Zrovna v tomto případě jsem si myslel, že eventListener funguje trochu jinak, než tomu ve skutečnosti je... Ale tak lepší být za blbce jednou a zeptat se, než se bát a být tím blbcem pořád.

 
Nahoru Odpovědět
19.1.2022 9:27
Avatar
Jan Novák
Člen
Avatar
Odpovídá na JsonKody
Jan Novák:19.1.2022 9:29

Aaha, děkuji, to jsem nevěděl.

 
Nahoru Odpovědět
19.1.2022 9:29
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:19.1.2022 10:11

Klidne muzes pouzit tento zapis.

canvas.onclick = draw;

Ale, pouzitim event-listeneru bys mel mit nad eventem lepsi kontrolu. Kdybys jako potreboval delat neco spesl.
event-listeren, listen je naslouchat. Je to nejaky program, ktery sleduje eventy a kdyz se nejaky stane, tak spusti funkci.
Mozna si to lepe predstavis jako planovac uloh. V 17 se ti spusti tv a zacne nahravat film. v 19 skonci nahravani a vypne tv.
V planovaci je

den-mesic-rok-cas "spusti funkci tv-nahravej"
den-mesic-rok-cas "vypni funkci tv-nahravej"
cas = kazdou 0.1s sleduj,  event = mouse-click, funkce = draw, spousteni = nespoustej znovu, pokud jeste fuknce neskoncila

addEventListener prida takovou ulohu na seznam.
Pokud vyuzivas event, mel bys tu funkci udelat tak, aby rychle zjistitla, zda vykona dalsi prikazy nebo ji rychle ukoncit, aby bylo mozne ji znovu spustit.

A pak tu mas funkce jako setTimeOut, setInterval, ktere funguji uplne stejne. Tam se casto omylem nastavi spousteni ikdyz zrovna funkce bezi.

A pak jsou tu funkce body.onload nebo img.onload, stahovani souboru (http-request, ajax). To jsou eventy, kdy se obsah postupne stahuje. A kdyz je dostahovan, tak se spousti onload. Tam je se da sledovat treba progres, kolik je stazeno. Ale, to se nedela, protoze sledovani eventu pro stahovani souboru brzdi stahovani. Misto toho se dela falesny progress nebo win ma rotujici kolecka.

 
Nahoru Odpovědět
19.1.2022 10:11
Avatar
JsonKody
Člen
Avatar
Odpovídá na JsonKody
JsonKody:19.1.2022 13:05

V pohode :D Doporucuju kouknout na ten muj kod, snazil jsem se ti to napsat nejlip jak to slo. Je tam i par komentaru ;) Jo a kdybys chtel, planoval jsem ze bych zkusil free naucit na discordu/twitchi nejake zaklady JS abych vedel jak to ucit.

Muj discord nick -> JsonKody#2976

Kod: https://codepen.io/…/pen/qBPwJzd?…

PS: porad me zajima jestli jsem ale pochopil spravne co to ma delat :D

 
Nahoru Odpovědět
19.1.2022 13:05
Avatar
Peter Mlich
Člen
Avatar
Odpovídá na JsonKody
Peter Mlich:19.1.2022 15:43

Mozna, ze presne to chtel.
Kod, co napsal, dela to, ze od mista kliknuti vykresli linky pod zadanym uhlem.

"generovala jen jedna čára"
https://developer.mozilla.org/…2D/clearRect
ctx.clearRect(x, y, width, height);
ctx.fillRect(0, 0, canvas.width, canvas.height);

Jo, jeste jsem prisel na to, ze <canvas style="width:xyz"> se chova u canvas ve Firefoxu jinak nez <canvas width="xyz">

 
Nahoru Odpovědět
19.1.2022 15:43
Avatar
Jan Novák
Člen
Avatar
Jan Novák:19.1.2022 17:20

Ano v podstatě je to přesně to co jsem potřeboval... Ani nezaleží na tom odkud kam se to vykresluje, jen mi šlo o to, aby se vždy kreslilo jen to co chci... Myslel jsem, že ten stary listener po opětovném kliknutí zanikne a nahradí ho ten nový, to byl ten problém...

 
Nahoru Odpovědět
19.1.2022 17:20
Avatar
JsonKody
Člen
Avatar
Odpovídá na Jan Novák
JsonKody:19.1.2022 18:39

od tohohle uz je to jen krucek k vytvoreni neceho jako je ta kreslici zelva v Pythonu :D

 
Nahoru Odpovědět
19.1.2022 18:39
Avatar
Jan Novák
Člen
Avatar
Odpovídá na JsonKody
Jan Novák:19.1.2022 19:56

Ano to je pravda :) Já vytvářím něco lehce víc komplexnějšího... Píšu webovou aplikaci pro generovaní Mandelbrotovy množiny a Juliových množin a grafické znazornění jejich vlastností, jestli víš o co jde..

 
Nahoru Odpovědět
19.1.2022 19:56
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:20.1.2022 8:12

Prepsani, to by melo jit tim
canvas.addEven­tListener('clic­k', draw, false); // canvas.onlick = ...

Ja listenery nepouzivam, tazke si ted nejsem uplne jisty, zda se to nezachova jako timeout a neprida novy. Jestli netreba nejdriv pouzit neco jako removeEventListener. Ale, mozna se remove udela samo pri add.
https://developer.mozilla.org/…ventListener

 
Nahoru Odpovědět
20.1.2022 8:12
Avatar
Jan Novák
Člen
Avatar
Jan Novák:20.1.2022 17:20

Ještě dotaz související s tímto tématem. Dejme tomu, že například nekreslím na canvas žlutý kruh, třeba jako základ pro kresbu slunka...a teď budu kreslit další věci jako jsou paprsky atd. Ale na konci se mi to nebude libit, tak se budu chtít vrátit zpet ke zlutemu kruhu a začnu s malováním znovu... Vím, že by to šlo udělat přes clearRect a nakreslení žlutého kruhu znovu... Ale já bych právě potřeboval aby tam ten žlutý kruh zůstal a nemusel se kreslit znovu... Totiž při generování fraktálních obrazců to vykreslení zabere relativně hodně času a tímto by se to hodně zrychlilo, kdybych byl schopny, jakoby přenést ten kruh do pozadí... Snad má otázka dává smysl.. děkuji

 
Nahoru Odpovědět
20.1.2022 17:20
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:23.1.2022 19:16

Muzes pouzit 2 canvasy?
Nebo, jestli ti jde o rozkopirovani stejneho obrazce pod ruznymi uhly, tak si ho vykresli do pomocneho canvas a pak vykopiruj.
google = js copy image from canvas1 to canvas2

https://developer.mozilla.org/…_with_canvas#…

https://stackoverflow.com/…nvas-locally

https://www.oreilly.com/…ch04s09.html
Tady treba kopiruji ze serie mini obrazku jeden do jineho canvasu. Delaji to teda primo v onload, ale to je detail.

 
Nahoru Odpovědět
23.1.2022 19:16
Avatar
Jan Novák
Člen
Avatar
Odpovídá na Peter Mlich
Jan Novák:24.1.2022 0:12

Právě ideální by bylo mít jeden canvas... Je to myšleno tak, že bych si to "uložil" do pozadí a na to pak maloval. Zkusím ještě pohledat.

Editováno 24.1.2022 0:14
 
Nahoru Odpovědět
24.1.2022 0:12
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:24.1.2022 10:03

No, ty muzes mit 2 pruhledne canvasy pres sebe (css position relative/absolute).

Nebo si muzes ulozit seznam vsech provedenych akci do pole a ty pak zopakovat. Jenze, to v pripade fraktalu muze znamenat furu narocnych vypoctu. Nebo si uloz informace o tech pixelech bokem do pole.

var i,i_end, list = [];
cykly ()
    list[i++] = vypocet() //[x, y, color]
i_end = i;
cykly (i=0; i<i_end; i++)
    zobraz(list[i])
Editováno 24.1.2022 10:05
 
Nahoru Odpovědět
24.1.2022 10:03
Avatar
JsonKody
Člen
Avatar
Odpovídá na Jan Novák
JsonKody:26.1.2022 11:26

Nejsem zdaleka odbornik na canvas, ale jak ho chapu ja tak si ho muzes predstavit jako papir a jedine co mas je pastelka ... thats it.
Je to jen jedna vrstva, v podstate to muzes brat ze je to obrazek. Jak mile na nej udelas caru je to obrazek cary atd. Neni tam zadny slozitejsi koncept. Kdyz se chces vratit musis proste nakreslit obrazek znovu v tom stavu do jakeho se chces vratit, takze to vyzaduje implementaci nejakeho systemu "nad tim" .. treba pouzit navrhovy vzor (v tech se taky zas tolik nevyznam) Memento, ktery slouzi k ukladani jednotlivych stavu takze je pak muzes vyvolavat jako v nejakem editoru (zmena zpet/vpred).
No preju hodne stesti :D

 
Nahoru Odpovědět
26.1.2022 11:26
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 19 zpráv z 19.