Skapa en digital etch en skiss

Sep 12, 2025
Hur

I den här handledningen tar vi den mekaniska ritningen Toy Etch en skiss som en inspiration och försök att genomföra dessa funktioner för moderna enheter, med webbteknik. Med hjälp av den (aptly het) duk, fokuserar vi först på tabletter, som är likadana i den autentiska leksaken. Vi kan utnyttja beröringshändelser för att styra uppringningarna och enhetens rörelsehändelser för att radera innehållet. Inte lämnar telefoner, vi kommer också att utforska hur man använder Websockets för att förbättra möjligheterna genom att dela upp kontrollerna och ritningsområdet.

01. Få tillgångarna

Denna handledning kommer att använda node.js. Innan vi börjar, gå till Filerilo , välj Gratis grejer och gratis innehåll bredvid handledningen - här kan du hämta de tillgångar du behöver för handledningen. Kör sedan kommandona nedan, som installerar beroenden och lanserar servern. Vi använder nod för att skapa en lokal värd , och det kommer också att tjäna oss senare för Websockets.

 npm installera
nodserver / index.js 

02. Använd Draw () -funktionen

I main.js , den dra() funktionen kommer att vara centrumpunkten för vår ansökan. Vi använder duk för att rita en linje mellan två punkter; Ursprunget (X1, Y1), där vi senast lämnade vår ritning och destinationen (X2, Y2), den nya punkten vi vill nå. Vi behöver nu utlösa den här funktionen för att observera någon form av ritning.

 Funktionsdrag (X1, Y1, X2, Y2) {
  // Kontext är att sättas globalt i init ()
  context.beginpath ();
  sammanhang.Moveto (x1, y1);
  context.lineto (x2, y2);
  sammanhang.stroke ();
} 

03. Implementera tangentbordshändelser

Innan vi implementerar ringer, låt oss snabbt lägga till en tangentbordslistare som kan utlösa vår dragfunktion. Du har redan fått de olika keycodes i exemplet, men du måste ändra lyssnaren något för att utlösa dra() Funktion som vi definierade tidigare. Uppdatera nu din webbläsare och se vad du kan rita med piltangenterna.

 document.addeventlistener ('Keydown', funktion (e) {
  / * Keycode-omkopplaren går här * /
  Draw (Math.floor (Prev_Horizontal), Math. Flor (Prev_Vertical), Math. Floor (Horisontell), Math. Floor (vertikal));
  prev_vertical = vertikal;
  prev_horizontal = horisontell;
}); 

04. Ändra storlek på duken

Du kanske har märkt att vårt canvaselement inte har en storlek tilldelad den än. För vår ritbord vill vi ha ett större utrymme, kanske även hela fönstret. Koden nedan tar hand om resize-evenemanget, men glöm inte att ringa JusteraFrame () i i det() också.

 Funktion JusteraFrame () {
  // Canvas definieras globalt i init ()
  canvas.width = window.innerwidth;
  canvas.height = window.innerheight;
}
Window.Addeventlistener ('Ändra storlek, JusteraFrame); 

05. Lägg till en ram

Vi vill att applikationen ska se ut som den ursprungliga leksaken så mycket som möjligt, så vi vill lägga till en ram runt ritningsområdet. För att göra det kan vi definiera ett marginalvärde och ändra CSS för #skiss till marginal: 20px auto; Att centrera duken horisontellt och håll ett större utrymme längst ner för ratten.

 VAR framemarginvertical = 122;
varramemarginhorizontal = 62;
Funktion JusteraFrame () {
  canvas.width = window.innerwidth - framemarginhorizontal;
  canvas.height = window.innerheight - framemarginvertical;
} 

06. Skapa uppringarna

Vi har redan gett dig CSS för ratterna i Public / CSS / Styles.CSS , så var god att ta en titt. Lägg sedan till två & lt; div & gt; Taggar under & lt; Canvas & GT; i HTML-filen, som beskrivs nedan. Som en konvention använder vi den vänstra ratten för horisontell ritning och höger för vertikal. Vi lägger också till nya variabler till i det() funktion för att förbereda sig för beröringshändelser.

 & lt; div id = "dialhorizontal" class = "dial" & gt; & lt; / div & gt;
& lt; div id = "dialogvertical" class = "dial" & gt; & lt; / div & gt; 
 VAR TILLETELEFT = DOCUMENT.GETELEMENTBYID ('DIALHORIZONTAL');
Var RegionLeft = Ny ZingTouch.region (TargetLeft);
Var TargetRight = document.getElementByD ('dialvertical');
Var RegionRight = Ny ZingTouch.region (TargetRight); 

07. Använd ZingTouch

The canvas with added dials, tied to the draw() function

Duken med tillsatta rattar, bundna till dragningen () -funktionen

ZingTouch är ett JavaScript-bibliotek som kan upptäcka olika touch-gester, och hanterar också mushändelser. Det är försett för dig i / Public / Lib / Mapp, som vi använder den för att styra våra rattar. Nedan följer genomförandet för vänster kontroll; Du måste replikera och ändra den för den andra sidan.

 RegionLeft.Bind (TargetLeft, "Rotate", Funktion (E) {
  om (e.detail.distancefromlast & lt; 0) {
  --horisontell;
  } annars {
  ++ horisontellt;
  }
  angleSizontal + = e.detail.distancefromlast;
  TargetLeft.Style.Transform = 'Rotera (' + ANGNEHORIZONTAL + 'DEG)';
  Rita (Math.floor (Prev_Horizontal), Math. Floor (Prev_Vertical), Math. Floor (Horisontell), Math. Floor (Prev_Vertical));
  prev_horizontal = horisontell;
}); 

08. Implementera uppringsgränser

För att blockera linjerna från att gå på skärmen använder vi Candraw () funktion, som returnerar en booleska. Vi passerar det riktningen, antingen "horisontell" eller "vertikal" och värdet av antingen den horisontella eller vertikala variabeln. Vi kallar den här funktionen i lyssnaren "Rotate" av båda ringarna, och endast om "sant" ökar vi vinkeln och ringer dra() fungera.

 Funktion Kandrot (riktning, värde) {
  var max = (riktning === 'horisontell')? (canvas.width) :( canvas.height);
  om (värde & lt; 2 || värde och gt; max - 2) {
  returnera false;
  }
  returnera sant;
} 

09. Undvik uppringningsproblem

Med de gränser vi just har implementerat finns det en chans att ratten kan fastna i ena änden om värdet går över gränsen, även med en decimalpunkt. För att undvika denna situation, bör vi hantera fallet där Candraw () är falskt och återställ värdet till en tidigare giltig, som visas här för den horisontella styrenheten:

 Om (Kandrot ("Horisontell", Horisontell)) {
  angleSizontal + = e.detail.distancefromlast;
  TargetLeft.Style.Transform = 'Rotera (' + ANGNEHORIZONTAL + 'DEG)';
  Rita (Math.floor (Prev_Horizontal), Math. Floor (Prev_Vertical), Math. Floor (Horisontell), Math. Floor (Prev_Vertical));
  prev_horizontal = horisontell;
} annars {
  horisontell = prev_horizontal;
} 

10. Få ritbordet på din surfplatta

Det rekommenderas alltid att testa på dina riktade enheter så tidigt som möjligt. Vår ansökan är nu i bra form och kan svara på beröringshändelser. Följ stegen om att komma åt Localhost på distans för att få ritbordet på din surfplatta.

Därefter använder vi Safari och utvecklingsmenyn för att inspektera programmet på en iPad. För Android-enheter, använd Chrome: // inspektera .

11. Testa accelerometern

Testing the accelerometer in Safari [click the icon to enlarge]

Testa accelerometern i Safari [Klicka på ikonen för att förstora]

Anslut din surfplatta till datorn via USB och inspektera programmet med hjälp av verktygsverktygen.

Med koden nedan på plats bör du kunna se de olika accelerationsvärdena, när du flyttar enheten runt. För att återställa duken har vi bestämt oss för att överväga en acceleration på X-axeln över 5 och sakta minska opaciteten ( radera ).

 Var Eraserat = 1; / * definiera som en global variabel * /
Window.Addeventlistener ('Devicemotion', Function (Event) {
  Console.log ('Acceleration ::', evenemang.acceleration);
  om (evenemang.acceleration.x & gt; 5) {
  Eraserat - = Math.abs (Event.Acceleration.x / 100);
  Console.log ("Radera ::", radera);
  }
}); 

12. Skaka för att radera

Vi har sett i föregående steg hur man kontrollerar för rörelse och acceleration. Vi behöver nu ringa Fadedrawing () när vårt tillstånd är uppfyllt. I det här fallet redrawerar vi en exakt kopia av duken på en annan opacitet.

Återställ globalalpha till 1 in dra() och sätt in globalcompositeoperation Tillbaka till källan.

 Funktion Fadedrawing () {
  Om (Eraserat & LT; 0) {
  context.ClearRect (0, 0, canvas.width, canvas.height);
  Eraserat = 1;
  lämna tillbaka;
  }
  Context.GlobalalPha = Eraserat;
  Context.GlobalCompositeOpperation = 'Copy';
  context.drawimage (canvas, 0, 0);
} 

13. Låt det se ut som den verkliga affären

Our application with shake-to-delete functionality

Vår ansökan med Shake-to-Ta bort funktionalitet

Hittills ser vår ansökan ganska snygg och platt. För att ge det lite djup lägger vi till en ramfärg, en skugga inuti ramen och lite volym på ratten. CSS för dialskuggorna är redan anordnade, men du måste lägga till de två elementen i slutet av kroppen.

Slutför CSS för de föreslagna elementen här:

 & lt; div id = "dialshadowhorizontal" klass = "skugga" & gt; & lt; / div & gt;
& lt; div id = "dialshadowvertical" class = "shadow" & gt; & lt; / div & gt; 
 kropp {
  Bakgrund: # 09cbf7;
}
#skiss {
  Box-Shadow: 2px 2px 10px rgba (0, 0, 0, .25) insats;
} 

14. Använd Websockets

I början av den här handledningen nämnde vi kort med Websockets via vår nodserver. Nu när du har en fristående ritningsplatta för tablett, kommer vi också att titta på att du gör det tillgängligt för din telefon. Telefoner kan dock vara för små för att visa både skärmen och kontrollerna. Vi använder därför socklar för att kommunicera mellan telefon och datorskärm.

15. Upptäck enhetens storlek

I huvud HTML-filen, byt ut main.js med extra.js . Den senare innehåller allt vi har gjort hittills, med ändringar för att hantera enheter och uttag, som vi inspekterar i följande steg. Ta en titt på detectdevice () - Denna metod blir nu kallad belastning istället för i det() och kommer att bestämma vilket "läge" att hantera för ansökan.

Nedan är det speciella fallet att en telefon upptäcks:

 Om (Window.InnerWidth & LT; 768) {
  socket = io.connect ();
  document.queryselector ('# skiss'). Ta bort ();
  Var Rings = Document.QuerySelectorAll ('. Dial, .shadow');
  [] .foreach.call (ringer, funktion (artikel) {
  objekt.classlist.add ('big');
  });
  iscontrols = sant;
  Framemargyvertical = 62;
  socket.emit ('Ready', {'Ready': 'Controls'});
} 

16. Från telefon till dator

From phone to computer, remotely drawing through sockets

Från telefon till dator, fjärrstart genom socklar

Genom hela extra.js Du kommer att märka bitar av kod som socket.emit () eller socket.on () . Det här är emittenterna och lyssnare för våra kontroller (telefon) och skärm (dator). Varje emitterad händelse måste gå igenom servern som ska distribueras till alla anslutna socklar. I server \ index.js Lägg till några fler lyssnare i funktionen "anslutning" och starta om nodservern.

 socket.on ('draw', funktion (data) {
  io.sockets.emit ("rita", data);
});
socket.on ('Erase', Function (Data) {
  io.sockets.emit ("Erase", data);
});
socket.on ('JusteraFrame', funktion (data) {
  screenwidth = data.screenwidth;
  ScreenHeight = Data.ScreenHeight;
  io.sockets.emit ("JusteraFrame", data);
}); 

17. Fixa telefonorientering

Besök localhost på din dator, samtidigt som du öppnar den på distans med din telefon (som du gjorde tidigare från din surfplatta). Du bör nu se en rad som dras på din skärm medan du vrider uppringningarna på din telefon. Du kommer dock att märka att rattarna inte passar ordentligt om telefonen är i stående läge.

Vi kan fixa detta med några CSS:

 @media skärm och (orientering: porträtt) {
  .dial.big # dialogvertical, .shadow.big # dialshadowvertical {
  Höger: Beräkna (50% - 75px);
  botten: 20px;
  Topp: Auto;
  }
  .dial.big # dialhorizontal, .shadow.big # dialshadowhorizontal {
  Vänster: Beräkna (50% - 75px);
  Topp: 20px;
  }
} 

18. Gör leksaken mer realistisk

Touching your tablet leaves some temporary fingerprints

Rörande din tablett lämnar några tillfälliga fingeravtryck

Låt oss komma tillbaka till vår Tablet-version. Tyvärr är vibration API inte tillgänglig på iOS, så vi kan inte implementera haptisk återkoppling när ratten vrids. I den ursprungliga leksaken kan du dock lämna tillfälliga svarta fingeravtrycksmärken på skärmen om du tryckte den. Vi kan lägga till en pekhändelse på enheten för att replikera den här funktionen.

Ställ in dessa lyssnare i i det() och utforska de funktioner som de kallar:

 om (typ === 'all') {
  canvas.addeventlistener ('Touchstart', funktion (e) {
  E.PreventDefault ();
  DrawfingerPrint (E.LayerX, E.Layery, True);
  });
  canvas.addeventlistener ('touchend', funktion (e) {
  HideFingerPrint (E.LayerX, E.Layery);
  });
} 

19. Spara en kopia av duken

I DrawfingerPrint () Metod, innan vi gör något annat, sparar vi en kopia av det aktuella läget för duken till ett dolt element som vi använder för att återställa vår ritning när vi rensar utskriften. Det händer bara vid första handen, och inte på de efterföljande samtalen som ökar utskriftens storlek varje 100ms.

 Funktion DrawfingerPrint (XPOS, YPOS, SAVECANVAS) {
  / * Delvis funktion, se Extra.js * /
  Om (SaveCanvas) {
  HiddenCanvas = document.createelement ('canvas');
  VAR HIDDENCONTEXT = HIDDENCANVAS.GETCONTEXT ('2D');
  hiddencanvas.width = canvas.bred;
  HiddenCanvas.Height = Canvas.Height;
  hiddencontext.drawimage (canvas, 0, 0);
  }
} 

20. Kör applikationen offline

Du kan nu göra ansökan verkligen fristående genom att spara den på din surfplatta som en startskärmsapp. Vi kommer inte att kunna göra detsamma för telefonen, eftersom det kräver anslutning till servern. I /offentlig , hitta filen som heter skiss.appcache och ersätta alla instanser av "localhost" av din IP-adress.

Ändra nu HTML för att läsa enligt följande:

 & lt; html lang = "en" manifest = "sketch.appcache" & gt; 

21. Spara ansökan

Besök nu programmet igen på din surfplatta och välj alternativet Lägg till i hemmet. En ny ikon ska visas på skrivbordet. Öppna det en gång när du fortfarande är ansluten till din localhost på distans. Cache Manifest vi satt upp tidigare hämtar alla nödvändiga filer för offlineanvändning i bakgrunden. Stäng av Wi-Fi och öppna appen igen. Voilà!

Denna artikel uppträdde ursprungligen i Web Designer Magazine Utgåva 263. Köp det här .

Läs mer:

  • 15 Web Apis du har aldrig hört talas om
  • En nybörjare guide till design av gränssnitt animationer
  • En guide till att skriva bättre CSS

Hur - Mest populära artiklar

Bygg en klientportal med WordPress

Hur Sep 12, 2025

(Bildkredit: Webbdesigner) Att ha ett område som tillåter användare att logga in och ladda ner eller visa dokument..


Kom igång med tillgångar i affinitetsdesigner

Hur Sep 12, 2025

När man arbetar med projekt som App Design eller Branding Collateral är det viktigt att det finns konsistens mellan olika eleme..


Hur man skapar glödande färger med oljemålningar

Hur Sep 12, 2025

Blir ombedd att beskriva mina målningsteknik är udda för mig, och uppriktigt är det svårt att göra. Jag är ..


5 saker du behöver för oljemålning

Hur Sep 12, 2025

Det finns en obefogad mystik runt oljemålning som har lagt några artister från att utforska dem. Om du känner till höger ..


Kom igång med WebGL med tre.js

Hur Sep 12, 2025

Webgl , som är allmänt stödd på alla moderna webbläsare, gör att du kan arbeta med hårdvaruaccelerat 3D-grafik..


Hur man ritar en våt figur

Hur Sep 12, 2025

Att måla en figur som ser trovärdigt våt kräver att du tar ett antal faktorer - en nyckel som är den typ av tyg som de har p..


Använd partiklar för att skapa en 3D-stänk

Hur Sep 12, 2025

Denna handledning tar en titt på hur du kan göra en flytande stänk eller kronans effekt och kan användas för att göra stän..


Kombinera traditionella och digitala färdigheter för att skapa ett komiskt skydd

Hur Sep 12, 2025

I åren blev jag skrämmad genom att arbeta digitalt. Något om plastbenet på en plastyta kände sig för att skada mig. Jag äl..


Kategorier