{"id":31519,"date":"2025-10-10T21:41:23","date_gmt":"2025-10-10T18:41:23","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=31519"},"modified":"2025-10-10T21:41:23","modified_gmt":"2025-10-10T18:41:23","slug":"html5-canvasi-vue-js-ile-kontrol-etmek","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/","title":{"rendered":"HTML5 Canvas&#8217;\u0131 Vue.js ile Kontrol Etmek"},"content":{"rendered":"<p><body><\/p>\n<h2>HTML5 Canvas&#8217;\u0131 Vue.js ile Kontrol Etmek<\/h2>\n<p>HTML5 Canvas, web taray\u0131c\u0131lar\u0131nda dinamik grafikler, oyunlar ve g\u00f6rselle\u015ftirmeler olu\u015fturmak i\u00e7in g\u00fc\u00e7l\u00fc bir ara\u00e7t\u0131r. Ancak, Canvas&#8217;\u0131n d\u00fc\u015f\u00fck seviyeli, imperative (emir kipiyle \u00e7al\u0131\u015fan) API&#8217;si, karma\u015f\u0131k uygulamalar\u0131n geli\u015ftirilmesini zorla\u015ft\u0131rabilir. \u0130\u015fte tam bu noktada Vue.js gibi modern bir JavaScript framework&#8217;\u00fc devreye girer. Vue.js&#8217;in reaktif veri ba\u011flama, bile\u015fen tabanl\u0131 mimarisi ve sezgisel API&#8217;si, Canvas \u00fczerindeki kontrol\u00fc \u00e7ok daha y\u00f6netilebilir ve \u00f6l\u00e7eklenebilir hale getirebilir. Bu makalede, HTML5 Canvas&#8217;\u0131 Vue.js ile nas\u0131l entegre edece\u011fimizi, temelden ileri seviyeye kadar farkl\u0131 yakla\u015f\u0131mlar\u0131, etkile\u015fim y\u00f6netimi, animasyonlar ve performans optimizasyonlar\u0131n\u0131 detayl\u0131 bir \u015fekilde inceleyece\u011fiz. Amac\u0131m\u0131z, Vue.js&#8217;in sa\u011flad\u0131\u011f\u0131 avantajlar\u0131 kullanarak Canvas&#8217;\u0131n potansiyelini tam anlam\u0131yla ortaya koymakt\u0131r.<\/p>\n<h3>HTML5 Canvas&#8217;\u0131 Anlamak<\/h3>\n<p>Canvas, web sayfas\u0131nda JavaScript ile dinamik olarak grafikler \u00e7izmek i\u00e7in kullan\u0131lan bir HTML5 elementidir. Vekt\u00f6r tabanl\u0131 SVG&#8217;nin aksine, Canvas raster (piksel tabanl\u0131) grafikler olu\u015fturur. Bu, \u00f6zellikle yo\u011fun piksel manip\u00fclasyonu gerektiren oyunlar, foto\u011fraf d\u00fczenleyiciler veya karma\u015f\u0131k veri g\u00f6rselle\u015ftirmeleri i\u00e7in idealdir.<\/p>\n<h4>Canvas Nedir?<\/h4>\n<p>Canvas, asl\u0131nda sadece bir &#8220;tuval&#8221;dir. \u00c7izim i\u015flemleri, JavaScript API&#8217;si arac\u0131l\u0131\u011f\u0131yla ger\u00e7ekle\u015ftirilir. Bir <code><canvas><\/code> etiketi ekledikten sonra, JavaScript ile bu etikete eri\u015fip <code>getContext('2d')<\/code> metodunu \u00e7a\u011f\u0131rarak bir \u00e7izim ba\u011flam\u0131 (rendering context) elde ederiz. Bu ba\u011flam, dikd\u00f6rtgenler, daireler, \u00e7izgiler, metinler, resimler gibi \u00e7e\u015fitli \u015fekilleri \u00e7izmek i\u00e7in kullan\u0131lacak metotlar\u0131 i\u00e7erir.<\/p>\n<pre><code class=\"language-html\"><canvas id=\"myCanvas\" width=\"500\" height=\"300\"><\/canvas><\/code><\/pre>\n<pre><code class=\"language-javascript\">const canvas = document.getElementById('myCanvas');\nconst ctx = canvas.getContext('2d');\n\n\/\/ Dikd\u00f6rtgen \u00e7izimi\nctx.fillStyle = 'blue';\nctx.fillRect(10, 10, 100, 50);\n\n\/\/ \u00c7izgi \u00e7izimi\nctx.strokeStyle = 'red';\nctx.lineWidth = 2;\nctx.beginPath();\nctx.moveTo(150, 10);\nctx.lineTo(200, 60);\nctx.stroke();<\/code><\/pre>\n<p>Canvas API&#8217;si, basit \u00e7izimden karma\u015f\u0131k d\u00f6n\u00fc\u015f\u00fcmlere (translate, rotate, scale), g\u00f6lgelendirmelere ve piksel manip\u00fclasyonuna kadar geni\u015f bir yelpazede yetenekler sunar. Ancak, her bir \u00e7izim i\u015flemi, mevcut durumu de\u011fi\u015ftirir ve genellikle \u00f6nceki durumu silip her \u015feyi yeniden \u00e7izmenizi gerektirir.<\/p>\n<h4>Canvas&#8217;\u0131n S\u0131n\u0131rl\u0131l\u0131klar\u0131<\/h4>\n<p>Canvas&#8217;\u0131n g\u00fcc\u00fc, ayn\u0131 zamanda onun en b\u00fcy\u00fck zorlu\u011funu da beraberinde getirir:<\/p>\n<p>*   <strong>Imperative API:<\/strong> Canvas ile \u00e7al\u0131\u015f\u0131rken, her \u015feyi manuel olarak \u00e7izmeniz gerekir. Bir dikd\u00f6rtgeni hareket ettirmek istedi\u011finizde, mevcut dikd\u00f6rtgeni silip yeni konumunda yeniden \u00e7izmeniz gerekir. Bu, durum y\u00f6netimi ve karma\u015f\u0131k etkile\u015fimler i\u00e7in olduk\u00e7a zahmetli olabilir.<br \/>\n*   <strong>Durum Y\u00f6netimi:<\/strong> \u00c7izilen nesnelerin konumlar\u0131n\u0131, renklerini, boyutlar\u0131n\u0131 ve di\u011fer \u00f6zelliklerini ayr\u0131 ayr\u0131 y\u00f6netmek, \u00f6zellikle \u00e7ok say\u0131da nesne oldu\u011funda h\u0131zla karma\u015f\u0131kla\u015f\u0131r.<br \/>\n*   <strong>Etkile\u015fim Y\u00f6netimi:<\/strong> Canvas \u00fczerindeki nesneler, DOM elementleri gibi do\u011frudan olay dinleyicilerine sahip de\u011fildir. Bir kullan\u0131c\u0131 belirli bir \u015fekle t\u0131klad\u0131\u011f\u0131nda, fare koordinatlar\u0131n\u0131 al\u0131p hangi \u015feklin t\u0131kland\u0131\u011f\u0131n\u0131 manuel olarak hesaplaman\u0131z (hit testing) gerekir.<br \/>\n*   <strong>Eri\u015filebilirlik:<\/strong> Canvas i\u00e7eri\u011fi, varsay\u0131lan olarak ekran okuyucular taraf\u0131ndan anla\u015f\u0131lamaz. Eri\u015filebilirlik i\u00e7in ek \u00f6nlemler alman\u0131z gerekir.<\/p>\n<p>Bu s\u0131n\u0131rl\u0131l\u0131klar, Canvas&#8217;\u0131 tek ba\u015f\u0131na kullan\u0131rken geli\u015ftirme s\u00fcrecini yava\u015flatabilir ve hatalara a\u00e7\u0131k hale getirebilir. \u0130\u015fte bu noktada Vue.js gibi bir framework&#8217;\u00fcn sundu\u011fu yap\u0131sal avantajlar devreye girer.<\/p>\n<h3>Vue.js&#8217;e Giri\u015f<\/h3>\n<p>Vue.js, kullan\u0131c\u0131 aray\u00fczleri olu\u015fturmak i\u00e7in a\u015famal\u0131 olarak benimsenebilir (progressively adoptable) bir JavaScript framework&#8217;\u00fcd\u00fcr. Reaktiflik, bile\u015fen tabanl\u0131 mimari ve basitlik \u00fczerine in\u015fa edilmi\u015ftir.<\/p>\n<h4>Vue.js Nedir?<\/h4>\n<p>Vue.js, veriyi DOM&#8217;a ba\u011flama ve aray\u00fcz\u00fc bile\u015fenlere ay\u0131rma konusunda m\u00fckemmeldir. Temel \u00f6zellikleri \u015funlard\u0131r:<\/p>\n<p>*   <strong>Reaktiflik:<\/strong> Vue.js&#8217;in en g\u00fc\u00e7l\u00fc \u00f6zelliklerinden biri reaktif veri sistemidir. Bir bile\u015fenin <code>data<\/code> \u00f6zelli\u011findeki bir de\u011fer de\u011fi\u015fti\u011finde, bu veriye ba\u011fl\u0131 olan DOM otomatik olarak g\u00fcncellenir. Bu, geli\u015ftiricilerin DOM manip\u00fclasyonu yerine uygulama verilerine odaklanmas\u0131n\u0131 sa\u011flar.<br \/>\n*   <strong>Bile\u015fen Tabanl\u0131 Mimari:<\/strong> Vue.js, uygulaman\u0131z\u0131 yeniden kullan\u0131labilir ve kendi kendine yeten bile\u015fenlere ay\u0131rman\u0131za olanak tan\u0131r. Her bile\u015fen kendi \u015fablonuna, beti\u011fine ve stil bilgilerine sahip olabilir. Bu, b\u00fcy\u00fck uygulamalar\u0131n y\u00f6netimini kolayla\u015ft\u0131r\u0131r.<br \/>\n*   <strong>Veri Ba\u011flama:<\/strong> <code>v-bind<\/code> (k\u0131saca <code>:<\/code>) ile HTML niteliklerini reaktif verilere ba\u011flayabilir, <code>v-model<\/code> ile iki y\u00f6nl\u00fc veri ba\u011flama sa\u011flayabilirsiniz.<br \/>\n*   <strong>Ya\u015fam D\u00f6ng\u00fcs\u00fc Kancalar\u0131:<\/strong> Vue bile\u015fenleri, olu\u015fturulma, monte edilme (mounted), g\u00fcncellenme (updated) ve kald\u0131r\u0131lma (unmounted) gibi belirli a\u015famalardan ge\u00e7er. Bu a\u015famalarda \u00e7al\u0131\u015fan ya\u015fam d\u00f6ng\u00fcs\u00fc kancalar\u0131 (<code>mounted<\/code>, <code>updated<\/code>, <code>beforeUnmount<\/code> vb.), belirli zamanlarda kod \u00e7al\u0131\u015ft\u0131rman\u0131za olanak tan\u0131r. Bu kancalar, Canvas entegrasyonu i\u00e7in kritik \u00f6neme sahiptir.<\/p>\n<p>Vue.js&#8217;in reaktif do\u011fas\u0131, Canvas&#8217;\u0131n imperative yap\u0131s\u0131yla birle\u015fti\u011finde, Canvas \u00fczerindeki \u00e7izim i\u015flemlerini \u00e7ok daha deklaratif bir \u015fekilde y\u00f6netmenin kap\u0131lar\u0131n\u0131 a\u00e7ar.<\/p>\n<h3>Vue.js ve Canvas&#8217;\u0131 Birle\u015ftirmek: Temel Yakla\u015f\u0131mlar<\/h3>\n<p>Vue.js ve HTML5 Canvas&#8217;\u0131 birle\u015ftirmenin birka\u00e7 temel yolu vard\u0131r. Her yakla\u015f\u0131m, belirli senaryolar i\u00e7in daha uygun olabilir.<\/p>\n<h4>Do\u011frudan DOM Eri\u015fimi ile Canvas Y\u00f6netimi<\/h4>\n<p>Bu, en basit yakla\u015f\u0131md\u0131r ve Vue.js&#8217;in <code>ref<\/code> \u00f6zelli\u011fi ile Canvas elementine do\u011frudan eri\u015fmeyi i\u00e7erir.<\/p>\n<p>1.  <strong>Canvas Elementini Tan\u0131mlama:<\/strong> Vue bile\u015feninizin \u015fablonunda bir <code><canvas><\/code> etiketi olu\u015fturun ve ona bir <code>ref<\/code> atay\u0131n.<\/p>\n<pre><code class=\"language-html\"><template>\n      <canvas ref=\"myCanvas\" width=\"600\" height=\"400\"><\/canvas>\n    <\/template><\/code><\/pre>\n<p>2.  <strong>Canvas Ba\u011flam\u0131na Eri\u015fme:<\/strong> Bile\u015fen monte edildi\u011finde (<code>mounted<\/code> ya\u015fam d\u00f6ng\u00fcs\u00fc kancas\u0131nda), <code>this.$refs.myCanvas<\/code> arac\u0131l\u0131\u011f\u0131yla Canvas elementine eri\u015febilir ve \u00e7izim ba\u011flam\u0131n\u0131 (<code>2d<\/code> context) alabilirsiniz.<\/p>\n<pre><code class=\"language-javascript\">export default {\n      data() {\n        return {\n          rectX: 50,\n          rectY: 50,\n          rectColor: 'red'\n        };\n      },\n      mounted() {\n        this.drawCanvas();\n      },\n      methods: {\n        drawCanvas() {\n          const canvas = this.$refs.myCanvas;\n          if (!canvas) return; \/\/ Canvas elementi hen\u00fcz yoksa \u00e7\u0131k\n          const ctx = canvas.getContext('2d');\n          \n          \/\/ Her yeniden \u00e7izimde tuvali temizle\n          ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n          \/\/ Reaktif verilerle \u00e7izim yap\n          ctx.fillStyle = this.rectColor;\n          ctx.fillRect(this.rectX, this.rectY, 100, 70);\n        }\n      }\n    };<\/code><\/pre>\n<p>3.  <strong>Reaktif Veri De\u011fi\u015fiminde Yeniden \u00c7izim:<\/strong> <code>rectX<\/code>, <code>rectY<\/code> veya <code>rectColor<\/code> gibi reaktif veriler de\u011fi\u015fti\u011finde Canvas&#8217;\u0131n otomatik olarak yeniden \u00e7izilmesini sa\u011flamak i\u00e7in <code>watch<\/code> \u00f6zelli\u011fini kullanabilirsiniz.<\/p>\n<pre><code class=\"language-javascript\">export default {\n      \/\/ ... (data, mounted, methods)\n      watch: {\n        rectX() {\n          this.drawCanvas();\n        },\n        rectY() {\n          this.drawCanvas();\n        },\n        rectColor() {\n          this.drawCanvas();\n        }\n      },\n      \/\/ ...\n    };<\/code><\/pre>\n<p>    Alternatif olarak, t\u00fcm ilgili reaktif verileri tek bir computed property&#8217;de toplay\u0131p onu izleyebilirsiniz, veya daha genel bir yakla\u015f\u0131m olarak <code>updated<\/code> ya\u015fam d\u00f6ng\u00fcs\u00fc kancas\u0131n\u0131 kullanabilirsiniz, ancak bu, Vue&#8217;nun DOM&#8217;u g\u00fcncelledi\u011fi her zaman tetiklenece\u011finden performans\u0131 olumsuz etkileyebilir. Genellikle <code>watch<\/code> daha kontroll\u00fc bir yakla\u015f\u0131md\u0131r.<\/p>\n<p>Bu yakla\u015f\u0131m, Canvas&#8217;\u0131 Vue bile\u015feni i\u00e7ine yerle\u015ftirir ve Vue&#8217;nun reaktifli\u011fini kullanarak \u00e7izim parametrelerini y\u00f6netmenizi sa\u011flar.<\/p>\n<h4>Reaktif Canvas Bile\u015fenleri Olu\u015fturma<\/h4>\n<p>Daha karma\u015f\u0131k uygulamalarda, her bir \u00e7izilebilir \u00f6\u011feyi (\u00f6rne\u011fin, bir daire, bir \u00e7izgi, bir resim) ayr\u0131 bir Vue bile\u015feni olarak d\u00fc\u015f\u00fcnmek faydal\u0131 olabilir. Bu &#8220;renderless&#8221; (DOM \u00e7\u0131kt\u0131s\u0131 \u00fcretmeyen) bile\u015fenler, Canvas \u00fczerinde bir \u015fey \u00e7izmek i\u00e7in <code>props<\/code> arac\u0131l\u0131\u011f\u0131yla veri al\u0131r ve <code>emit<\/code> olaylar\u0131 arac\u0131l\u0131\u011f\u0131yla ana bile\u015fene geri bildirim sa\u011flar.<\/p>\n<p>Bu yakla\u015f\u0131mda, asl\u0131nda Canvas bile\u015fenleri DOM&#8217;a herhangi bir <code><canvas><\/code> etiketi render etmez. Bunun yerine, ana Canvas bile\u015feni, alt bile\u015fenlerden gelen \u00e7izim talimatlar\u0131n\u0131 toplar ve hepsini tek bir Canvas \u00fczerinde \u00e7izer.<\/p>\n<p><strong>\u00d6rnek: <code><CanvasCircle><\/code> Bile\u015feni<\/strong><\/p>\n<pre><code class=\"language-javascript\">\/\/ CanvasCircle.vue (Bu bile\u015fen DOM'a hi\u00e7bir \u015fey render etmez)\nexport default {\n  props: {\n    x: { type: Number, required: true },\n    y: { type: Number, required: true },\n    radius: { type: Number, default: 20 },\n    color: { type: String, default: 'blue' },\n    id: { type: String, required: true } \/\/ Benzersiz kimlik\n  },\n  \/\/ Bu bile\u015fen, ebeveynine kendini \u00e7izmesi i\u00e7in bilgi g\u00f6nderecek.\n  \/\/ Ger\u00e7ek DOM'a render edilmedi\u011fi i\u00e7in template bo\u015f olabilir veya sadece slot i\u00e7erebilir.\n  template: '<div><\/div>',\n  \n  \/\/ \u00c7izim bilgisini ebeveyne emit etmek i\u00e7in ya\u015fam d\u00f6ng\u00fcs\u00fc kancalar\u0131n\u0131 kullan\u0131r\u0131z.\n  mounted() {\n    this.$parent.addShape(this);\n  },\n  updated() {\n    this.$parent.updateShape(this);\n  },\n  beforeUnmount() {\n    this.$parent.removeShape(this);\n  },\n  computed: {\n    \/\/ \u00c7izim i\u00e7in gerekli t\u00fcm verileri i\u00e7eren bir obje d\u00f6nd\u00fcr\u00fcr\n    drawData() {\n      return {\n        type: 'circle',\n        x: this.x,\n        y: this.y,\n        radius: this.radius,\n        color: this.color,\n        id: this.id\n      };\n    }\n  }\n};<\/code><\/pre>\n<p><strong>Ana Canvas Bile\u015feni (<code>App.vue<\/code> veya <code>CanvasContainer.vue<\/code>)<\/strong><\/p>\n<pre><code class=\"language-html\"><template>\n  <canvas ref=\"canvas\" :width=\"canvasWidth\" :height=\"canvasHeight\"><\/canvas>\n  <slot><\/slot> <!-- Alt bile\u015fenler buraya yerle\u015fecek -->\n<\/template>\n\n<script>\nexport default {\n  props: {\n    canvasWidth: { type: Number, default: 800 },\n    canvasHeight: { type: Number, default: 600 }\n  },\n  data() {\n    return {\n      ctx: null,\n      shapes: new Map() \/\/ ID'ye g\u00f6re \u015fekilleri saklamak i\u00e7in Map\n    };\n  },\n  mounted() {\n    const canvas = this.$refs.canvas;\n    this.ctx = canvas.getContext('2d');\n    this.drawAllShapes();\n  },\n  methods: {\n    addShape(shapeComponent) {\n      this.shapes.set(shapeComponent.id, shapeComponent.drawData);\n      this.drawAllShapes();\n    },\n    updateShape(shapeComponent) {\n      this.shapes.set(shapeComponent.id, shapeComponent.drawData);\n      this.drawAllShapes();\n    },\n    removeShape(shapeComponent) {\n      this.shapes.delete(shapeComponent.id);\n      this.drawAllShapes();\n    },\n    drawAllShapes() {\n      if (!this.ctx) return;\n      this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);\n\n      this.shapes.forEach(shape => {\n        if (shape.type === 'circle') {\n          this.ctx.beginPath();\n          this.ctx.arc(shape.x, shape.y, shape.radius, 0, Math.PI * 2);\n          this.ctx.fillStyle = shape.color;\n          this.ctx.fill();\n        }\n        \/\/ Di\u011fer \u015fekil tipleri buraya eklenebilir\n      });\n    }\n  },\n  \/\/ Alt bile\u015fenlerin props'lar\u0131 de\u011fi\u015fti\u011finde yeniden \u00e7izim yapmas\u0131n\u0131 sa\u011flamak i\u00e7in\n  \/\/ bir watcher eklemek yerine, alt bile\u015fenlerin kendileri 'updated' kancas\u0131nda\n  \/\/ ebeveyni bilgilendirerek yeniden \u00e7izimi tetikler.\n};\n<\/script><\/code><\/pre>\n<p><strong>Kullan\u0131m:<\/strong><\/p>\n<pre><code class=\"language-html\"><template>\n  <CanvasContainer>\n    <CanvasCircle id=\"circle1\" :x=\"100\" :y=\"100\" :radius=\"30\" color=\"green\" \/>\n    <CanvasCircle id=\"circle2\" :x=\"250\" :y=\"150\" :radius=\"40\" :color=\"dynamicColor\" \/>\n    <button @click=\"changeColor\">Rengi De\u011fi\u015ftir<\/button>\n  <\/CanvasContainer>\n<\/template>\n\n<script>\nimport CanvasContainer from '.\/CanvasContainer.vue';\nimport CanvasCircle from '.\/CanvasCircle.vue';\n\nexport default {\n  components: {\n    CanvasContainer,\n    CanvasCircle\n  },\n  data() {\n    return {\n      dynamicColor: 'purple'\n    };\n  },\n  methods: {\n    changeColor() {\n      this.dynamicColor = this.dynamicColor === 'purple' ? 'orange' : 'purple';\n    }\n  }\n};\n<\/script><\/code><\/pre>\n<p>Bu yakla\u015f\u0131m, Canvas&#8217;\u0131n d\u00fc\u015f\u00fck seviyeli API&#8217;sini soyutlayarak, bile\u015fen tabanl\u0131 geli\u015ftirmenin avantajlar\u0131n\u0131 Canvas&#8217;a ta\u015f\u0131r. Her &#8220;Canvas bile\u015feni&#8221;, kendi \u00e7izim mant\u0131\u011f\u0131n\u0131 kaps\u00fcller ve reaktif verilerle g\u00fcncellendi\u011finde, ana Canvas&#8217;\u0131n yeniden \u00e7izilmesini tetikler.<\/p>\n<h3>Geli\u015fmi\u015f Canvas Kontrol\u00fc ve Etkile\u015fim<\/h3>\n<p>Canvas ile etkile\u015fim ve animasyonlar, Vue.js&#8217;in reaktif g\u00fcc\u00fcyle daha kolay y\u00f6netilebilir.<\/p>\n<h4>Etkinlik Y\u00f6netimi<\/h4>\n<p>Canvas elementine do\u011frudan DOM olay dinleyicileri ekleyebiliriz (<code>@click<\/code>, <code>@mousemove<\/code>, <code>@mousedown<\/code>, <code>@mouseup<\/code>). Ancak, bu olaylar Canvas&#8217;\u0131n kendisine aittir, \u00e7izilen nesnelere de\u011fil. Bir nesneye t\u0131klan\u0131p t\u0131klanmad\u0131\u011f\u0131n\u0131 anlamak i\u00e7in &#8220;hit testing&#8221; yapmam\u0131z gerekir.<\/p>\n<pre><code class=\"language-html\"><template>\n  <canvas \n    ref=\"myCanvas\" \n    @mousedown=\"handleMouseDown\" \n    @mousemove=\"handleMouseMove\" \n    @mouseup=\"handleMouseUp\"\n    width=\"600\" \n    height=\"400\"\n  ><\/canvas>\n<\/template>\n\n<script>\nexport default {\n  data() {\n    return {\n      ctx: null,\n      shapes: [\n        { id: 'rect1', x: 50, y: 50, width: 100, height: 70, color: 'blue', isDragging: false },\n        { id: 'circle1', x: 200, y: 150, radius: 40, color: 'green', isDragging: false }\n      ],\n      draggedShapeId: null,\n      offsetX: 0,\n      offsetY: 0\n    };\n  },\n  mounted() {\n    this.ctx = this.$refs.myCanvas.getContext('2d');\n    this.drawShapes();\n  },\n  methods: {\n    drawShapes() {\n      if (!this.ctx) return;\n      this.ctx.clearRect(0, 0, this.$refs.myCanvas.width, this.$refs.myCanvas.height);\n\n      this.shapes.forEach(shape => {\n        if (shape.id.startsWith('rect')) {\n          this.ctx.fillStyle = shape.color;\n          this.ctx.fillRect(shape.x, shape.y, shape.width, shape.height);\n        } else if (shape.id.startsWith('circle')) {\n          this.ctx.beginPath();\n          this.ctx.arc(shape.x, shape.y, shape.radius, 0, Math.PI * 2);\n          this.ctx.fillStyle = shape.color;\n          this.ctx.fill();\n        }\n      });\n    },\n    getMousePos(event) {\n      const rect = this.$refs.myCanvas.getBoundingClientRect();\n      return {\n        x: event.clientX - rect.left,\n        y: event.clientY - rect.top\n      };\n    },\n    isPointInShape(point, shape) {\n      if (shape.id.startsWith('rect')) {\n        return point.x > shape.x && point.x < shape.x + shape.width &#038;&#038;\n               point.y > shape.y && point.y < shape.y + shape.height;\n      } else if (shape.id.startsWith('circle')) {\n        const dist = Math.sqrt(Math.pow(point.x - shape.x, 2) + Math.pow(point.y - shape.y, 2));\n        return dist < shape.radius;\n      }\n      return false;\n    },\n    handleMouseDown(event) {\n      const mousePos = this.getMousePos(event);\n      for (let i = this.shapes.length - 1; i >= 0; i--) { \/\/ \u00dcstteki \u015fekle \u00f6ncelik ver\n        const shape = this.shapes[i];\n        if (this.isPointInShape(mousePos, shape)) {\n          this.draggedShapeId = shape.id;\n          this.offsetX = mousePos.x - shape.x;\n          this.offsetY = mousePos.y - shape.y;\n          break;\n        }\n      }\n    },\n    handleMouseMove(event) {\n      if (!this.draggedShapeId) return;\n      \n      const mousePos = this.getMousePos(event);\n      const shape = this.shapes.find(s => s.id === this.draggedShapeId);\n      if (shape) {\n        shape.x = mousePos.x - this.offsetX;\n        shape.y = mousePos.y - this.offsetY;\n        this.drawShapes(); \/\/ \u015eeklin konumunu g\u00fcncelledik, yeniden \u00e7iz\n      }\n    },\n    handleMouseUp() {\n      this.draggedShapeId = null;\n    }\n  }\n};\n<\/script><\/code><\/pre>\n<p>Bu \u00f6rnekte, <code>shapes<\/code> ad\u0131nda bir reaktif dizi i\u00e7inde t\u00fcm \u00e7izim nesnelerinin durumunu tutuyoruz. Fare olaylar\u0131 tetiklendi\u011finde, <code>isPointInShape<\/code> fonksiyonu ile hangi \u015fekle t\u0131kland\u0131\u011f\u0131n\u0131 veya s\u00fcr\u00fcklenmek istendi\u011fini belirliyoruz. \u015eeklin konumu g\u00fcncellendi\u011finde, Vue&#8217;nun reaktif sistemi otomatik olarak <code>shapes<\/code> dizisini g\u00fcnceller ve <code>drawShapes<\/code> metodunu \u00e7a\u011f\u0131rarak Canvas&#8217;\u0131 yeniden \u00e7izer.<\/p>\n<h4>Animasyonlar<\/h4>\n<p>Canvas \u00fczerinde animasyonlar genellikle <code>requestAnimationFrame<\/code> kullan\u0131larak olu\u015fturulur. Bu, taray\u0131c\u0131n\u0131n ekran yenileme h\u0131z\u0131na senkronize olarak \u00e7izim yapman\u0131z\u0131 sa\u011flar.<\/p>\n<pre><code class=\"language-javascript\">export default {\n  data() {\n    return {\n      ctx: null,\n      ball: { x: 50, y: 50, radius: 20, dx: 2, dy: 2, color: 'orange' },\n      animationFrameId: null\n    };\n  },\n  mounted() {\n    this.ctx = this.$refs.myCanvas.getContext('2d');\n    this.startAnimation();\n  },\n  beforeUnmount() {\n    this.stopAnimation(); \/\/ Bile\u015fen kald\u0131r\u0131ld\u0131\u011f\u0131nda animasyonu durdur\n  },\n  methods: {\n    drawBall() {\n      this.ctx.clearRect(0, 0, this.$refs.myCanvas.width, this.$refs.myCanvas.height);\n      this.ctx.beginPath();\n      this.ctx.arc(this.ball.x, this.ball.y, this.ball.radius, 0, Math.PI * 2);\n      this.ctx.fillStyle = this.ball.color;\n      this.ctx.fill();\n    },\n    updateBall() {\n      \/\/ Topun konumunu g\u00fcncelle\n      this.ball.x += this.ball.dx;\n      this.ball.y += this.ball.dy;\n\n      \/\/ Kenar \u00e7arp\u0131\u015fmalar\u0131n\u0131 kontrol et\n      if (this.ball.x + this.ball.radius > this.$refs.myCanvas.width || this.ball.x - this.ball.radius < 0) {\n        this.ball.dx = -this.ball.dx;\n      }\n      if (this.ball.y + this.ball.radius > this.$refs.myCanvas.height || this.ball.y - this.ball.radius < 0) {\n        this.ball.dy = -this.ball.dy;\n      }\n    },\n    animate() {\n      this.updateBall();\n      this.drawBall();\n      this.animationFrameId = requestAnimationFrame(this.animate);\n    },\n    startAnimation() {\n      this.animationFrameId = requestAnimationFrame(this.animate);\n    },\n    stopAnimation() {\n      if (this.animationFrameId) {\n        cancelAnimationFrame(this.animationFrameId);\n        this.animationFrameId = null;\n      }\n    }\n  }\n};<\/code><\/pre>\n<p>Burada, <code>ball<\/code> objesinin <code>x<\/code> ve <code>y<\/code> koordinatlar\u0131 reaktif olarak g\u00fcncellenir. <code>animate<\/code> metodu, <code>requestAnimationFrame<\/code> ile s\u00fcrekli olarak \u00e7a\u011fr\u0131l\u0131r, topun konumunu g\u00fcnceller (<code>updateBall<\/code>) ve ard\u0131ndan Canvas'\u0131 yeniden \u00e7izer (<code>drawBall<\/code>). <code>beforeUnmount<\/code> kancas\u0131nda animasyonun durdurulmas\u0131, bellek s\u0131z\u0131nt\u0131lar\u0131n\u0131 ve gereksiz i\u015flemci kullan\u0131m\u0131n\u0131 \u00f6nler.<\/p>\n<h4>\u00c7oklu Nesneleri Y\u00f6netme<\/h4>\n<p>Daha \u00f6nce \"Reaktif Canvas Bile\u015fenleri\" b\u00f6l\u00fcm\u00fcnde g\u00f6sterildi\u011fi gibi, Canvas \u00fczerindeki \u00e7oklu nesneleri y\u00f6netmenin en etkili yollar\u0131ndan biri, her nesnenin durumunu bir Vue reaktif dizisi veya haritas\u0131 i\u00e7inde tutmakt\u0131r. Ana Canvas bile\u015feni, bu diziyi veya haritay\u0131 izler ve herhangi bir de\u011fi\u015fiklik oldu\u011funda t\u00fcm Canvas'\u0131 yeniden \u00e7izer.<\/p>\n<p>Vue'nun <code>v-for<\/code> direktifi, bu t\u00fcr senaryolarda \u00e7ok kullan\u0131\u015fl\u0131d\u0131r. Ana Canvas bile\u015feninizin i\u00e7indeki bir <code><slot><\/code> i\u00e7inde <code>v-for<\/code> kullanarak alt Canvas bile\u015fenlerini dinamik olarak olu\u015fturabilirsiniz:<\/p>\n<pre><code class=\"language-html\"><!-- Ana CanvasContainer.vue i\u00e7inde -->\n<template>\n  <canvas ref=\"canvas\" :width=\"canvasWidth\" :height=\"canvasHeight\"><\/canvas>\n  <template v-for=\"shape in shapesData\" :key=\"shape.id\">\n    <!-- Bu k\u0131s\u0131m asl\u0131nda DOM'a render edilmez, sadece Vue'nun reaktifli\u011fini tetikler -->\n    <CanvasCircle \n      v-if=\"shape.type === 'circle'\"\n      :id=\"shape.id\"\n      :x=\"shape.x\"\n      :y=\"shape.y\"\n      :radius=\"shape.radius\"\n      :color=\"shape.color\"\n    \/>\n    <!-- Di\u011fer \u015fekil tipleri i\u00e7in benzer \u015fekilde -->\n  <\/template>\n<\/template><\/code><\/pre>\n<p>Bu yakla\u015f\u0131m, Canvas nesnelerinin eklenmesi, silinmesi veya g\u00fcncellenmesi gibi i\u015flemleri Vue'nun reaktif veri y\u00f6netimiyle uyumlu hale getirir.<\/p>\n<h3>Performans Optimizasyonlar\u0131<\/h3>\n<p>B\u00fcy\u00fck veya karma\u015f\u0131k Canvas uygulamalar\u0131nda performans kritik \u00f6neme sahiptir. Vue.js ile \u00e7al\u0131\u015f\u0131rken bile Canvas'\u0131n do\u011fas\u0131 gere\u011fi dikkat etmemiz gereken baz\u0131 optimizasyonlar vard\u0131r.<\/p>\n<h4>Gereksiz Yeniden \u00c7izimleri Engelleme<\/h4>\n<p>Canvas'\u0131n en b\u00fcy\u00fck performans maliyeti, her \u015feyi ba\u015ftan sona yeniden \u00e7izmesidir.<br \/>\n*   <strong>Dirty Rectangles (Kirli Dikd\u00f6rtgenler):<\/strong> Sadece de\u011fi\u015fen veya hareket eden b\u00f6lgeleri yeniden \u00e7izmek, performans\u0131 \u00f6nemli \u00f6l\u00e7\u00fcde art\u0131rabilir. Bunun i\u00e7in <code>clearRect<\/code> metodunu t\u00fcm tuval yerine sadece de\u011fi\u015fen alan \u00fczerinde kullan\u0131rs\u0131n\u0131z. Ancak bu, \u00fcst \u00fcste binen nesnelerle karma\u015f\u0131kla\u015fabilir.<br \/>\n*   <strong>Off-screen Canvas:<\/strong> Baz\u0131 statik veya nadiren de\u011fi\u015fen \u00f6\u011feleri (\u00f6rne\u011fin, arka plan, karma\u015f\u0131k desenler) g\u00f6r\u00fcnmez bir off-screen canvas \u00fczerinde \u00f6nceden \u00e7izip, ana canvas'a <code>drawImage<\/code> ile kopyalamak, ana \u00e7izim d\u00f6ng\u00fcs\u00fcndeki y\u00fck\u00fc azalt\u0131r.<\/p>\n<h4>Web Workers<\/h4>\n<p>Yo\u011fun hesaplamalar (\u00f6rne\u011fin, karma\u015f\u0131k algoritmalar, b\u00fcy\u00fck veri i\u015fleme) ana JavaScript i\u015f par\u00e7ac\u0131\u011f\u0131n\u0131 bloke edebilir ve aray\u00fcz\u00fcn donmas\u0131na neden olabilir. Web Workers, bu t\u00fcr hesaplamalar\u0131 ayr\u0131 bir i\u015f par\u00e7ac\u0131\u011f\u0131nda \u00e7al\u0131\u015ft\u0131rman\u0131za olanak tan\u0131r. Canvas'\u0131n piksel verilerini (<code>ImageData<\/code>) bir Web Worker'a g\u00f6nderip orada manip\u00fcle edip geri alarak performans\u0131 art\u0131rabilirsiniz. Ancak, Web Worker'lar do\u011frudan DOM'a veya Canvas ba\u011flam\u0131na eri\u015femez, bu nedenle veri transferi maliyetini g\u00f6z \u00f6n\u00fcnde bulundurmak gerekir.<\/p>\n<h4>Taray\u0131c\u0131 Optimizasyonlar\u0131<\/h4>\n<p>*   <strong><code>will-change<\/code> CSS \u00d6zelli\u011fi:<\/strong> Canvas elementine <code>will-change: contents;<\/code> veya <code>will-change: transform;<\/code> gibi CSS \u00f6zellikleri eklemek, taray\u0131c\u0131ya bu elementin yak\u0131n gelecekte de\u011fi\u015fece\u011fini bildirir ve taray\u0131c\u0131n\u0131n GPU h\u0131zland\u0131rmas\u0131n\u0131 daha etkin kullanmas\u0131na yard\u0131mc\u0131 olabilir.<br \/>\n*   <strong>Donan\u0131m H\u0131zland\u0131rma:<\/strong> Taray\u0131c\u0131lar genellikle Canvas \u00e7izimlerini donan\u0131m h\u0131zland\u0131rma ile yapmaya \u00e7al\u0131\u015f\u0131r. Bu genellikle otomatik olsa da, a\u015f\u0131r\u0131 b\u00fcy\u00fck Canvas'lar veya \u00e7ok karma\u015f\u0131k \u00e7izimler bazen yaz\u0131l\u0131m tabanl\u0131 \u00e7izime geri d\u00f6n\u00fclmesine neden olabilir. Canvas boyutunu makul tutmak ve \u00e7izim komutlar\u0131n\u0131 optimize etmek \u00f6nemlidir.<\/p>\n<h3>Pratik Uygulama \u00d6rne\u011fi: Basit Bir \u00c7izim Tahtas\u0131<\/h3>\n<p>Vue.js ile bir \u00e7izim tahtas\u0131 olu\u015fturmak, Canvas etkile\u015fimini ve reaktif veri y\u00f6netimini birle\u015ftiren iyi bir \u00f6rnektir.<\/p>\n<pre><code class=\"language-html\"><template>\n  <div class=\"canvas-board-container\">\n    <div class=\"toolbar\">\n      <input type=\"color\" v-model=\"currentColor\">\n      <button @click=\"clearCanvas\">Temizle<\/button>\n    <\/div>\n    <canvas \n      ref=\"drawingCanvas\" \n      :width=\"canvasWidth\" \n      :height=\"canvasHeight\"\n      @mousedown=\"startDrawing\"\n      @mousemove=\"draw\"\n      @mouseup=\"stopDrawing\"\n      @mouseleave=\"stopDrawing\"\n    ><\/canvas>\n  <\/div>\n<\/template>\n\n<script>\nexport default {\n  data() {\n    return {\n      canvasWidth: 800,\n      canvasHeight: 600,\n      ctx: null,\n      isDrawing: false,\n      currentColor: '#000000',\n      drawnLines: [] \/\/ \u00c7izilen t\u00fcm \u00e7izgileri saklamak i\u00e7in reaktif dizi\n    };\n  },\n  mounted() {\n    const canvas = this.$refs.drawingCanvas;\n    this.ctx = canvas.getContext('2d');\n    this.ctx.lineWidth = 2;\n    this.ctx.lineCap = 'round';\n    this.ctx.strokeStyle = this.currentColor;\n  },\n  watch: {\n    currentColor(newColor) {\n      this.ctx.strokeStyle = newColor;\n    },\n    \/\/ drawnLines dizisi de\u011fi\u015fti\u011finde Canvas'\u0131 yeniden \u00e7iz\n    drawnLines: {\n      handler() {\n        this.redrawAllLines();\n      },\n      deep: true \/\/ Dizinin i\u00e7indeki objeler de\u011fi\u015fti\u011finde de tetiklenmesi i\u00e7in\n    }\n  },\n  methods: {\n    getMousePos(event) {\n      const rect = this.$refs.drawingCanvas.getBoundingClientRect();\n      return {\n        x: event.clientX - rect.left,\n        y: event.clientY - rect.top\n      };\n    },\n    startDrawing(event) {\n      this.isDrawing = true;\n      const pos = this.getMousePos(event);\n      \/\/ Yeni bir \u00e7izgi ba\u015flat\n      this.drawnLines.push({\n        color: this.currentColor,\n        points: [{ x: pos.x, y: pos.y }]\n      });\n      this.ctx.beginPath();\n      this.ctx.moveTo(pos.x, pos.y);\n    },\n    draw(event) {\n      if (!this.isDrawing) return;\n      const pos = this.getMousePos(event);\n      \n      \/\/ Mevcut \u00e7izgiye nokta ekle\n      const currentLine = this.drawnLines[this.drawnLines.length - 1];\n      currentLine.points.push({ x: pos.x, y: pos.y });\n\n      \/\/ Canvas \u00fczerinde \u00e7izim yap\n      this.ctx.lineTo(pos.x, pos.y);\n      this.ctx.stroke();\n    },\n    stopDrawing() {\n      this.isDrawing = false;\n      this.ctx.closePath();\n    },\n    redrawAllLines() {\n      if (!this.ctx) return;\n      this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); \/\/ T\u00fcm tuvali temizle\n\n      this.drawnLines.forEach(line => {\n        this.ctx.beginPath();\n        this.ctx.strokeStyle = line.color;\n        if (line.points.length > 0) {\n          this.ctx.moveTo(line.points[0].x, line.points[0].y);\n          for (let i = 1; i < line.points.length; i++) {\n            this.ctx.lineTo(line.points[i].x, line.points[i].y);\n          }\n        }\n        this.ctx.stroke();\n        this.ctx.closePath();\n      });\n    },\n    clearCanvas() {\n      this.drawnLines = []; \/\/ T\u00fcm \u00e7izgileri sil, watcher tetiklenir ve canvas temizlenir\n    }\n  }\n};\n<\/script>\n\n<style scoped>\n.canvas-board-container {\n  border: 1px solid #ccc;\n  display: inline-block;\n}\n.toolbar {\n  padding: 10px;\n  background-color: #f0f0f0;\n  border-bottom: 1px solid #ccc;\n  display: flex;\n  gap: 10px;\n  align-items: center;\n}\ncanvas {\n  background-color: #fff;\n  display: block;\n}\n<\/style><\/code><\/pre>\n<p>Bu \u00f6rnekte:<br \/>\n*   <code>drawnLines<\/code> ad\u0131nda reaktif bir dizi, t\u00fcm \u00e7izilen \u00e7izgileri ve onlar\u0131n noktalar\u0131n\u0131 saklar. Her \u00e7izgi kendi rengine sahiptir.<br \/>\n*   <code>startDrawing<\/code>, <code>draw<\/code>, <code>stopDrawing<\/code> metotlar\u0131, fare olaylar\u0131n\u0131 i\u015fler ve <code>drawnLines<\/code> dizisine yeni noktalar ekler.<br \/>\n*   <code>drawnLines<\/code> dizisi <code>watch<\/code> ile derinlemesine izlenir (<code>deep: true<\/code>). Dizinin i\u00e7eri\u011fi (yani bir \u00e7izgiye yeni bir nokta eklenmesi) de\u011fi\u015fti\u011finde <code>redrawAllLines<\/code> metodu tetiklenir.<br \/>\n*   <code>redrawAllLines<\/code> metodu, Canvas'\u0131 tamamen temizler ve <code>drawnLines<\/code> dizisindeki t\u00fcm \u00e7izgileri ba\u015ftan sona yeniden \u00e7izer. Bu, Canvas'\u0131n mevcut durumunu her zaman reaktif veriyle senkronize tutar.<br \/>\n*   <code>currentColor<\/code> da reaktif olarak izlenir ve \u00e7izim rengini dinamik olarak ayarlar.<\/p>\n<h3>Alternatif Yakla\u015f\u0131mlar ve K\u00fct\u00fcphaneler<\/h3>\n<p>Vue.js ile Canvas'\u0131 kontrol etmenin daha soyut ve g\u00fc\u00e7l\u00fc yollar\u0131 da mevcuttur.<\/p>\n<h4>Renderless Bile\u015fenler<\/h4>\n<p>Daha \u00f6nce bahsedilen <code><CanvasCircle><\/code> \u00f6rne\u011fi, bir t\u00fcr \"renderless\" bile\u015fendi. Bu bile\u015fenler kendi DOM'unu render etmezler, bunun yerine Vue'nun reaktifli\u011fini ve bile\u015fen ya\u015fam d\u00f6ng\u00fcs\u00fc kancalar\u0131n\u0131 kullanarak ebeveyn bile\u015fenle (genellikle ana Canvas bile\u015feni) ileti\u015fim kurarlar. Bu, \u00e7izim mant\u0131\u011f\u0131n\u0131 kaps\u00fcllemenin ve Vue'nun bile\u015fen modelini Canvas'a uygulaman\u0131n g\u00fc\u00e7l\u00fc bir yoludur.<\/p>\n<p>Renderless bile\u015fenler, karma\u015f\u0131k Canvas uygulamalar\u0131nda kodun d\u00fczenini ve yeniden kullan\u0131labilirli\u011fini \u00f6nemli \u00f6l\u00e7\u00fcde art\u0131rabilir. \u00d6rne\u011fin, bir <code>Draggable<\/code> renderless bile\u015feni, bir Canvas nesnesinin s\u00fcr\u00fcklenme mant\u0131\u011f\u0131n\u0131 kaps\u00fclleyebilir ve bu mant\u0131\u011f\u0131 herhangi bir Canvas nesnesine kolayca uygulayabilir.<\/p>\n<h4>Vue ile Entegre Canvas K\u00fct\u00fcphaneleri<\/h4>\n<p>HTML5 Canvas API'si d\u00fc\u015f\u00fck seviyeli oldu\u011fu i\u00e7in, Konva.js, Fabric.js, Pixi.js gibi k\u00fct\u00fcphaneler bu API'nin \u00fczerine daha y\u00fcksek seviyeli, nesne odakl\u0131 bir soyutlama katman\u0131 in\u015fa eder. Bu k\u00fct\u00fcphaneler, \"sahne grafi\u011fi\" (scene graph) yakla\u015f\u0131m\u0131n\u0131 kullanarak Canvas \u00fczerindeki her nesneyi (dikd\u00f6rtgen, daire, metin vb.) bir obje olarak temsil eder. Bu objeler, kendi \u00f6zelliklerine (konum, renk, boyut) ve metotlar\u0131na (s\u00fcr\u00fckle, d\u00f6nd\u00fcr) sahiptir.<\/p>\n<p>Vue.js'i bu k\u00fct\u00fcphanelerle entegre etmek, geli\u015ftirme deneyimini daha da iyile\u015ftirebilir:<\/p>\n<p>*   <strong>Konva.js (vue-konva):<\/strong> Vue-konva, Konva.js'i Vue bile\u015fenleri olarak sarmalar. <code><v-stage><\/code>, <code><v-layer><\/code>, <code><v-rect><\/code>, <code><v-circle><\/code> gibi bile\u015fenler kullanarak deklaratif bir \u015fekilde Canvas i\u00e7eri\u011fi olu\u015fturabilirsiniz. Bu, Vue'nun reaktifli\u011fini ve bile\u015fen modelini do\u011frudan Konva.js'in sahne grafi\u011fiyle birle\u015ftirir. Bir Konva nesnesinin \u00f6zelli\u011fi de\u011fi\u015fti\u011finde, Vue bunu alg\u0131lar ve Konva sahnesini otomatik olarak g\u00fcnceller.<br \/>\n*   <strong>Fabric.js:<\/strong> Fabric.js, Canvas \u00fczerinde nesneleri se\u00e7me, ta\u015f\u0131ma, boyutland\u0131rma gibi etkile\u015fimleri kolayla\u015ft\u0131ran g\u00fc\u00e7l\u00fc bir k\u00fct\u00fcphanedir. Vue ile entegre ederken, Fabric.js sahnesini bir Vue bile\u015feni i\u00e7inde ba\u015flat\u0131r ve Fabric nesnelerinin \u00f6zelliklerini Vue'nun reaktif verileriyle ba\u011flars\u0131n\u0131z. Fabric'in olay sistemini Vue olaylar\u0131na d\u00f6n\u00fc\u015ft\u00fcrebilirsiniz.<br \/>\n*   <strong>Pixi.js:<\/strong> Daha \u00e7ok oyun ve y\u00fcksek performansl\u0131 grafikler i\u00e7in tasarlanm\u0131\u015f bir 2D WebGL renderer'\u0131d\u0131r (Canvas fallback'i de vard\u0131r). Vue ile Pixi.js'i kullanmak i\u00e7in, Pixi sahnesini bir Vue bile\u015feni i\u00e7inde ba\u015flat\u0131r ve Pixi DisplayObject'lerinin \u00f6zelliklerini Vue reaktif verileriyle y\u00f6netirsiniz. <code>vue-pixi<\/code> gibi k\u00fct\u00fcphaneler bu entegrasyonu kolayla\u015ft\u0131r\u0131r.<\/p>\n<p>Bu k\u00fct\u00fcphaneleri kullanmak, Canvas'\u0131n d\u00fc\u015f\u00fck seviyeli karma\u015f\u0131kl\u0131\u011f\u0131n\u0131 b\u00fcy\u00fck \u00f6l\u00e7\u00fcde azalt\u0131r ve \u00f6zellikle s\u00fcr\u00fckle-b\u0131rak, yeniden boyutland\u0131rma, katmanlama gibi karma\u015f\u0131k etkile\u015fimler gerektiren uygulamalar i\u00e7in harika bir \u00e7\u00f6z\u00fcmd\u00fcr. Vue'nun reaktifli\u011fi, bu k\u00fct\u00fcphanelerin nesnelerinin durumunu y\u00f6netmek i\u00e7in do\u011fal bir uyum sa\u011flar.<\/p>\n<h3>Sonu\u00e7<\/h3>\n<p>HTML5 Canvas, web \u00fczerinde zengin ve dinamik g\u00f6rsel deneyimler olu\u015fturmak i\u00e7in vazge\u00e7ilmez bir ara\u00e7t\u0131r. Ancak, d\u00fc\u015f\u00fck seviyeli ve imperative API'si, \u00f6zellikle karma\u015f\u0131k uygulamalarda geli\u015ftirme s\u00fcrecini zorla\u015ft\u0131rabilir. Vue.js'in reaktif veri ba\u011flama, bile\u015fen tabanl\u0131 mimari ve sezgisel API'si, bu zorluklar\u0131n \u00fcstesinden gelmek i\u00e7in g\u00fc\u00e7l\u00fc bir \u00e7\u00f6z\u00fcm sunar.<\/p>\n<p>Vue.js ile Canvas'\u0131 birle\u015ftirerek, \u00e7izim parametrelerini reaktif verilerle y\u00f6netebilir, bile\u015fenler arac\u0131l\u0131\u011f\u0131yla \u00e7izilebilir \u00f6\u011feleri soyutlayabilir ve etkile\u015fimli grafikler ile animasyonlar\u0131 daha deklaratif bir \u015fekilde olu\u015fturabiliriz. <code>ref<\/code> kullan\u0131m\u0131yla do\u011frudan Canvas eri\u015fimi, renderless bile\u015fenler arac\u0131l\u0131\u011f\u0131yla soyutlama veya Konva.js gibi \u00fc\u00e7\u00fcnc\u00fc taraf k\u00fct\u00fcphaneleri Vue bile\u015fenleriyle sarmalama gibi farkl\u0131 yakla\u015f\u0131mlar, projenizin ihtiya\u00e7lar\u0131na g\u00f6re esneklik sa\u011flar.<\/p>\n<p>Performans optimizasyonlar\u0131 (kirli dikd\u00f6rtgenler, off-screen canvas, Web Workers) ve taray\u0131c\u0131 ipu\u00e7lar\u0131, b\u00fcy\u00fck \u00f6l\u00e7ekli ve y\u00fcksek performansl\u0131 Canvas uygulamalar\u0131 geli\u015ftirirken g\u00f6z \u00f6n\u00fcnde bulundurulmas\u0131 gereken kritik noktalard\u0131r.<\/p>\n<p>Sonu\u00e7 olarak, Vue.js ve HTML5 Canvas'\u0131n birle\u015fimi, geli\u015ftiricilere hem Canvas'\u0131n ham g\u00fcc\u00fcn\u00fc kullanma hem de Vue'nun modern web geli\u015ftirme paradigmalar\u0131n\u0131n sa\u011flad\u0131\u011f\u0131 \u00fcretkenlik ve y\u00f6netilebilirlik avantajlar\u0131ndan yararlanma imkan\u0131 sunar. Bu sinerji, interaktif veri g\u00f6rselle\u015ftirmelerinden karma\u015f\u0131k oyunlara kadar geni\u015f bir yelpazedeki uygulamalar\u0131n geli\u015ftirilmesini \u00e7ok daha eri\u015filebilir ve keyifli hale getirir.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"HTML5 Canvas&#8217;\u0131 Vue.js ile Kontrol Etmek\nHTML5 Canvas, web taray\u0131c\u0131lar\u0131nda dinamik grafikler, oyunlar ve g\u00f6rselle\u015ftirmeler olu\u015fturmak i\u00e7in g\u00fc","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1402],"tags":[],"class_list":{"0":"post-31519","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-vue","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>HTML5 Canvas&#039;\u0131 Vue.js ile Kontrol Etmek - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HTML5 Canvas&#039;\u0131 Vue.js ile Kontrol Etmek\" \/>\n<meta property=\"og:description\" content=\"HTML5 Canvas&#039;\u0131 Vue.js ile Kontrol Etmek HTML5 Canvas, web taray\u0131c\u0131lar\u0131nda dinamik grafikler, oyunlar ve g\u00f6rselle\u015ftirmeler olu\u015fturmak i\u00e7in g\u00fc\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-10T18:41:23+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"HTML5 Canvas&#8217;\u0131 Vue.js ile Kontrol Etmek\",\"datePublished\":\"2025-10-10T18:41:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/\"},\"wordCount\":2614,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"Vue\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/\",\"name\":\"HTML5 Canvas'\u0131 Vue.js ile Kontrol Etmek - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-10-10T18:41:23+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"HTML5 Canvas&#8217;\u0131 Vue.js ile Kontrol Etmek\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"HTML5 Canvas'\u0131 Vue.js ile Kontrol Etmek - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/","og_locale":"tr_TR","og_type":"article","og_title":"HTML5 Canvas'\u0131 Vue.js ile Kontrol Etmek","og_description":"HTML5 Canvas'\u0131 Vue.js ile Kontrol Etmek HTML5 Canvas, web taray\u0131c\u0131lar\u0131nda dinamik grafikler, oyunlar ve g\u00f6rselle\u015ftirmeler olu\u015fturmak i\u00e7in g\u00fc","og_url":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-10-10T18:41:23+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"16 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"HTML5 Canvas&#8217;\u0131 Vue.js ile Kontrol Etmek","datePublished":"2025-10-10T18:41:23+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/"},"wordCount":2614,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["Vue"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/","url":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/","name":"HTML5 Canvas'\u0131 Vue.js ile Kontrol Etmek - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-10-10T18:41:23+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/html5-canvasi-vue-js-ile-kontrol-etmek\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"HTML5 Canvas&#8217;\u0131 Vue.js ile Kontrol Etmek"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/31519","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=31519"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/31519\/revisions"}],"predecessor-version":[{"id":31520,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/31519\/revisions\/31520"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=31519"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=31519"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=31519"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}