9

DrawingArea

Objective
  • Responder
    • View
      • DrawingArea

In the console of the browser, display the values of all the options:

canvas.getOptions()
Object { size: (2) […], hflip: false, vflip: false, grayscale: false, sepia: false, blur: false, invert: 0, contrast: 1, saturate: 1, brightness: 1, … }

Change some filter values of the canvas:

canvas.sepia=true
canvas.sepia=false
canvas.hflip=true
canvas.opacity=0.5
canvas.opacity=1

Change the size of the canvas:

canvas.size=[640,360]

Edit the file testDrawingArea.phtml in the folder tests:

  1. <?php $tagname='img'; ?>

Set the PHP variable $tagname to the value 'video'. Reload the page.

Try the value 'canvas'.

  1. function DrawingArea() {
  2.     View.call(this);
  3.  
  4.     this._width = this._height = 0;
  5.  
  6.     this._hflip = this._vflip = false;
  7.  
  8.     this._grayscale = this._sepia = this._blur = false;
  9.  
  10.     this._contrast = this._saturate = this._brightness = 1;
  11.  
  12.     this._invert = 0;
  13.  
  14.     this._opacity = 1;
  15.  
  16.     this._ctx = null;
  17.  
  18.     this._image = null;
  19. }
  20.  
  21. DrawingArea.prototype = Object.create(View.prototype);
  22.  
  23. Object.defineProperty(DrawingArea.prototype, 'constructor', { value: DrawingArea, enumerable: false, writable: true });
  24.  
  25. Object.defineProperty(DrawingArea.prototype, 'size', {
  26.     get:    function() {
  27.                 return [this._width, this._height];
  28.             },
  29.     set:    function(size) {
  30.                 if (! (Array.isArray(size) && size.length == 2))
  31.                     throw new TypeError();
  32.  
  33.                 const [width, height] = size;
  34.  
  35.                 if (! (Number.isInteger(width) && Number.isInteger(height)))
  36.                     throw new TypeError();
  37.  
  38.                 if (width < 0 || height < 0)
  39.                     throw new RangeError();
  40.  
  41.                 if (this._width != width || this._height != height) {
  42.                     this._width = width;
  43.                     this._height = height;
  44.  
  45.                     if (this.interfaced()) {
  46.                         this._ctxTransform();
  47.                         this._drawImage();
  48.                     }
  49.                 }
  50.             }
  51. });
  52.  
  53. Object.defineProperty(DrawingArea.prototype, 'hflip', {
  54.     get:    function() {
  55.                 return this._hflip;
  56.             },
  57.     set:    function(hflip) {
  58.                 if (this._hflip != hflip) {
  59.                     this._hflip = hflip ? true : false;
  60.  
  61.                     if (this.interfaced()) {
  62.                         this._ctxTransform();
  63.                         this._drawImage();
  64.                     }
  65.                 }
  66.             }
  67. });
  68.  
  69. Object.defineProperty(DrawingArea.prototype, 'vflip', {
  70.     get:    function() {
  71.                 return this._vflip;
  72.             },
  73.     set:    function(vflip) {
  74.                 if (this._vflip != vflip) {
  75.                     this._vflip = vflip ? true : false;
  76.  
  77.                     if (this.interfaced()) {
  78.                         this._ctxTransform();
  79.                         this._drawImage();
  80.                     }
  81.                 }
  82.             }
  83. });
  84.  
  85. Object.defineProperty(DrawingArea.prototype, 'grayscale', {
  86.     get:    function() {
  87.                 return this._grayscale;
  88.             },
  89.     set:    function(grayscale) {
  90.                 if (this._grayscale != grayscale) {
  91.                     this._grayscale = grayscale ? true : false;
  92.  
  93.                     if (this.interfaced()) {
  94.                         this._ctxFilter();
  95.                         this._drawImage();
  96.                     }
  97.                 }
  98.             }
  99. });
  100.  
  101. Object.defineProperty(DrawingArea.prototype, 'sepia', {
  102.     get:    function() {
  103.                 return this._sepia;
  104.             },
  105.     set:    function(sepia) {
  106.                 if (this._sepia != sepia) {
  107.                     this._sepia = sepia ? true : false;
  108.  
  109.                     if (this.interfaced()) {
  110.                         this._ctxFilter();
  111.                         this._drawImage();
  112.                     }
  113.                 }
  114.             }
  115. });
  116.  
  117. Object.defineProperty(DrawingArea.prototype, 'blur', {
  118.     get:    function() {
  119.                 return this._blur;
  120.             },
  121.     set:    function(blur) {
  122.                 if (this._blur != blur) {
  123.                     this._blur = blur ? true : false;
  124.  
  125.                     if (this.interfaced()) {
  126.                         this._ctxFilter();
  127.                         this._drawImage();
  128.                     }
  129.                 }
  130.             }
  131. });
  132.  
  133. Object.defineProperty(DrawingArea.prototype, 'invert', {
  134.     get:    function() {
  135.                 return this._invert;
  136.             },
  137.     set:    function(invert) {
  138.                 if (typeof invert !== 'number')
  139.                     throw new TypeError();
  140.  
  141.                 if (invert < 0 || invert > 1)
  142.                     throw new RangeError();
  143.  
  144.                 if (this._invert != invert) {
  145.                     this._invert = invert;
  146.  
  147.                     if (this.interfaced()) {
  148.                         this._ctxFilter();
  149.                         this._drawImage();
  150.                     }
  151.                 }
  152.             }
  153. });
  154.  
  155. Object.defineProperty(DrawingArea.prototype, 'contrast', {
  156.     get:    function() {
  157.                 return this._contrast;
  158.             },
  159.     set:    function(contrast) {
  160.                 if (typeof contrast !== 'number')
  161.                     throw new TypeError();
  162.  
  163.                 if (contrast < 0)
  164.                     throw new RangeError();
  165.  
  166.                 if (this._contrast != contrast) {
  167.                     this._contrast = contrast;
  168.  
  169.                     if (this.interfaced()) {
  170.                         this._ctxFilter();
  171.                         this._drawImage();
  172.                     }
  173.                 }
  174.             }
  175. });
  176.  
  177. Object.defineProperty(DrawingArea.prototype, 'saturate', {
  178.     get:    function() {
  179.                 return this._saturate;
  180.             },
  181.     set:    function(saturate) {
  182.                 if (typeof saturate !== 'number')
  183.                     throw new TypeError();
  184.  
  185.                 if (saturate < 0)
  186.                     throw new RangeError();
  187.  
  188.                 if (this._saturate != saturate) {
  189.                     this._saturate = saturate;
  190.  
  191.                     if (this.interfaced()) {
  192.                         this._ctxFilter();
  193.                         this._drawImage();
  194.                     }
  195.                 }
  196.             }
  197. });
  198.  
  199. Object.defineProperty(DrawingArea.prototype, 'brightness', {
  200.     get:    function() {
  201.                 return this._brightness;
  202.             },
  203.     set:    function(brightness) {
  204.                 if (typeof brightness !== 'number')
  205.                     throw new TypeError();
  206.  
  207.                 if (brightness < 0)
  208.                     throw new RangeError();
  209.  
  210.                 if (this._brightness != brightness) {
  211.                     this._brightness = brightness;
  212.  
  213.                     if (this.interfaced()) {
  214.                         this._ctxFilter();
  215.                         this._drawImage();
  216.                     }
  217.                 }
  218.             }
  219. });
  220.  
  221. Object.defineProperty(DrawingArea.prototype, 'opacity', {
  222.     get:    function() {
  223.                 return this._opacity;
  224.             },
  225.     set:    function(opacity) {
  226.                 if (typeof opacity !== 'number')
  227.                     throw new TypeError();
  228.  
  229.                 if (opacity < 0 || opacity > 1)
  230.                     throw new RangeError();
  231.  
  232.                 if (this._opacity != opacity) {
  233.                     this._opacity = opacity;
  234.  
  235.                     if (this.interfaced()) {
  236.                         this._ctxFilter();
  237.                         this._drawImage();
  238.                     }
  239.                 }
  240.             }
  241. });
  242.  
  243. DrawingArea.prototype.getOptions = function() {
  244.     const options = {
  245.         size:   [this._width, this._height],
  246.         hflip:      this._hflip,
  247.         vflip:      this._vflip,
  248.         grayscale:  this._grayscale,
  249.         sepia:      this._sepia,
  250.         blur:       this._blur,
  251.         invert:     this._invert,
  252.         contrast:   this._contrast,
  253.         saturate:   this._saturate,
  254.         brightness: this._brightness,
  255.         opacity:    this._opacity
  256.     };
  257.  
  258.     return options;
  259. };
  260.  
  261. DrawingArea.prototype.setOptions = function(options) {
  262.     const {
  263.         size = [this._width, this._height],
  264.         hflip = this._hflip,
  265.         vflip = this._vflip,
  266.         grayscale = this._grayscale,
  267.         sepia = this._sepia,
  268.         blur = this._blur,
  269.         invert = this._invert,
  270.         contrast = this._contrast,
  271.         saturate = this._saturate,
  272.         brightness = this._brightness,
  273.         opacity = this._opacity
  274.     } = options || {};
  275.  
  276.     if (! (Array.isArray(size) && size.length == 2))
  277.         throw new TypeError();
  278.  
  279.     const [width, height] = size;
  280.  
  281.     if (! (Number.isInteger(width) && Number.isInteger(height)))
  282.         throw new TypeError();
  283.  
  284.     if (width < 0 || height < 0)
  285.         throw new RangeError();
  286.  
  287.     this._width = width;
  288.     this._height = height;
  289.  
  290.     this._hflip = hflip ? true : false;
  291.     this._vflip = vflip ? true : false;
  292.     this._grayscale = grayscale ? true : false;
  293.     this._sepia = sepia ? true : false;
  294.     this._blur = blur ? true : false;
  295.  
  296.     if (! (typeof invert === 'number' && typeof contrast === 'number' && typeof saturate === 'number' && typeof brightness === 'number' && typeof opacity === 'number'))
  297.         throw new TypeError();
  298.  
  299.     if (invert < 0 || contrast < 0 || saturate < 0 || brightness < 0)
  300.         throw new RangeError();
  301.  
  302.     if (opacity < 0 || opacity > 1)
  303.         throw new RangeError();
  304.  
  305.     this._invert = invert;
  306.     this._contrast = contrast;
  307.     this._saturate = saturate;
  308.     this._brightness = brightness;
  309.  
  310.     this._opacity = opacity;
  311.  
  312.     if (this.interfaced()) {
  313.         this._ctxTransform();
  314.         this._drawImage();
  315.     }
  316.  
  317.     return this;
  318. };
  319.  
  320. DrawingArea.prototype.setImage = function(w) {
  321.     this._image = w;
  322.  
  323.     this._drawImage();
  324.  
  325.     return this;
  326. }
  327.  
  328. DrawingArea.prototype.setWidget = function(w) {
  329.     if (! (w.tagName == 'IMG' || w.tagName == 'VIDEO' || w.tagName == 'CANVAS'))
  330.         throw new TypeError();
  331.  
  332.     const canvas = document.createElement('canvas');
  333.  
  334.     this._ctx = canvas.getContext('2d');
  335.  
  336.     View.prototype.setWidget.call(this, canvas);
  337.  
  338.     w.style.display = 'none';
  339.  
  340.     w.after(canvas);
  341.  
  342.     this._image = w;
  343.  
  344.     if (this._width == 0) {
  345.         this._width = w.width;
  346.         this._height = w.height;
  347.     }
  348.  
  349.     this._ctxTransform();
  350.  
  351.     switch (w.tagName) {
  352.     case 'IMG':
  353.         this._drawImage();  // NEEDED for Chrome
  354.         w.addEventListener('load', () => this._drawImage(), { once: true });
  355.         break;
  356.     case 'VIDEO':
  357.         w.addEventListener('loadeddata', () => this._drawImage(), { once: true });
  358.         break;
  359.     case 'CANVAS':
  360.     default:
  361.         this._drawImage();
  362.     }
  363.  
  364.     return this;
  365. }
  366.  
  367. DrawingArea.prototype._ctxFilter = function() {
  368.     let filter = [];
  369.  
  370.     if (this._grayscale)
  371.         filter.push('grayscale(1)');
  372.  
  373.     if (this._sepia)
  374.         filter.push('sepia(1)');
  375.  
  376.     if (this._blur)
  377.         filter.push('blur(8px)');
  378.  
  379.     if (this._invert != 0)
  380.         filter.push(`invert(${this._invert})`);
  381.  
  382.     if (this._contrast != 1)
  383.         filter.push(`contrast(${this._contrast})`);
  384.  
  385.     if (this._saturate != 1)
  386.         filter.push(`saturate(${this._saturate})`);
  387.  
  388.     if (this._brightness != 1)
  389.         filter.push(`brightness(${this._brightness})`);
  390.  
  391.     if (this._opacity != 1)
  392.         filter.push(`opacity(${this._opacity})`);
  393.  
  394.     this._ctx.filter = filter.length ? filter.join(' ') : 'none';
  395. }
  396.  
  397. DrawingArea.prototype._ctxTransform = function() {
  398.     this._widget.width = this._width;
  399.     this._widget.height = this._height;
  400.  
  401.     this._ctx.transform(this._hflip ? -1 : 1, 0, 0, this._vflip ? -1 : 1, this._hflip ? this._widget.width : 0, this._vflip ? this._widget.height : 0);
  402.  
  403.     this._ctxFilter();
  404. }
  405.  
  406. DrawingArea.prototype._drawImage = function() {
  407.     if (this._widget.width == 0 || this._widget.height == 0)
  408.         return;
  409.  
  410.     this._ctx.clearRect(0, 0, this._widget.width, this._widget.height);
  411.  
  412.     let steps = Math.ceil(Math.log(Math.max(this._image.width / this._widget.width, this._image.height / this._widget.height)) / Math.log(2));
  413.  
  414.     if (steps > 1) {
  415.         const oc = document.createElement('canvas');
  416.         const octx = oc.getContext('2d');
  417.  
  418.         let ocw = this._image.width * 0.5, och = this._image.height * 0.5;
  419.  
  420.         oc.width = ocw;
  421.         oc.height = och;
  422.  
  423.         octx.drawImage(this._image, 0, 0, ocw, och);
  424.  
  425.         while (--steps > 1)
  426.             octx.drawImage(oc, 0, 0, ocw, och, 0, 0, ocw *= 0.5, och *= 0.5);
  427.  
  428.         this._ctx.drawImage(oc, 0, 0, ocw, och, 0, 0, this._widget.width, this._widget.height);
  429.     }
  430.     else
  431.         this._ctx.drawImage(this._image, 0, 0, this._widget.width, this._widget.height);
  432. }
Test
  1. <?php $maxwidth=320; ?>
  2. <?php $tagname='img'; ?>
  1. switch ($tagname) {
  2. case 'img':
  3.     $src='/files/images/htmlcssjs.jpg';
  4.     $width=1280;
  5.     $height=720;
  6.     break;
  7. case 'video':
  8.     $src='/files/videos/Horloge.webm';
  9.     $type='video/webm';
  10.     $width=854;
  11.     $height=480;
  12.     break;
  13. case 'canvas':
  14.     $width=600;
  15.     $height=$width;
  16.     break;
  17. }
  1. <?php $id=uniqid('id'); ?>
  1. <div id="<?php echo $id; ?>" class="noprint">
  2. <div class="test_display">
  3. <?php if ($tagname == 'img'): ?>
  4. <img src="<?php echo $src; ?>" alt="" width="<?php echo $width; ?>" height="<?php echo $height; ?>" hidden/>
  5. <?php elseif ($tagname == 'video'): ?>
  6. <video width="<?php echo $width; ?>" height="<?php echo $height; ?>" preload="auto">
  7. <source src="<?php echo $src; ?>" type="<?php echo $type; ?>" />
  8. </video>
  9. <?php elseif ($tagname == 'canvas'): ?>
  10. <canvas width="<?php echo $width; ?>" height="<?php echo $height; ?>"></canvas>
  11. <?php endif; ?>
  12. </div>
  13. </div>
  1. <?php head('javascript', '/objectivejs/Objective.js'); ?>
  2. <?php head('javascript', '/objectivejs/Responder.js'); ?>
  3. <?php head('javascript', '/objectivejs/View.js'); ?>
  4. <?php head('javascript', '/objectivejs/DrawingArea.js'); ?>
  1. (function() {
  2.     const canvas = document.querySelector('#<?php echo $id; ?> canvas');
  3.     const ctx = canvas.getContext('2d');
  4.  
  5.     const w = canvas.width / 2;
  6.     const h = canvas.height / 2;
  7.  
  8.     ctx.fillStyle = '#FD0';
  9.     ctx.fillRect(0, 0, w, h);
  10.     ctx.fillStyle = '#6C0';
  11.     ctx.fillRect(w, 0, w, h);
  12.     ctx.fillStyle = '#09F';
  13.     ctx.fillRect(0, h, w, h);
  14.     ctx.fillStyle = '#F30';
  15.     ctx.fillRect(w, h, w, h);
  16.     ctx.fillStyle = '#FFF';
  17.  
  18.     ctx.globalAlpha = 0.2;
  19.  
  20.     for (let i = 0; i < 7; i++) {
  21.         ctx.beginPath();
  22.         ctx.arc(w, h, w / 10 + h / 10 * i, 0, Math.PI * 2, true);
  23.         ctx.fill();
  24.     }
  25. })();
  1. const width = <?php echo $width; ?>;
  2. const height = <?php echo $height; ?>;
  3. const maxwidth = <?php echo $maxwidth; ?>;
  4.  
  5. const ratio = Math.round(width / height * 100) / 100;
  1. const image = document.querySelector('#<?php echo $id; ?> <?php echo $tagname; ?>');
  1. const canvas = new DrawingArea();
  2.  
  3. canvas.size = [maxwidth, Math.ceil(maxwidth / ratio)];
  4.  
  5. canvas.setManagedWidget(image);
SEE ALSO

View, VideoClip, Editing a clip

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].