Draggable
La classe Draggable ajoute la capacité de déplacer un élément avec la souris ou avec un doigt.
Cliquez dans l'image pour démarrer l'animation. Cliquez de nouveau pour l'arrêter.
Placez le pointeur de la souris sur l'image et appuyez sur la barre d'espace.
Glissez le clip dans la <div>
qui le contient avec la souris ou avec un doigt sur un écran tactile.
Déplacez le clip près du bord droit de la <div>
. Essayez de la redimensionner.
- function Draggable() {
- View.call(this);
- this._draggable = false;
- this._dragged = false;
- }
- Draggable.prototype = Object.create(View.prototype);
- Object.defineProperty(Draggable.prototype, 'constructor', { value: Draggable, enumerable: false, writable: true });
- Draggable.prototype.isDraggable = function() {
- return this._draggable;
- };
- Draggable.prototype.enableDrag = function() {
- if (this._draggable)
- return this;
- if (!this.isManaged())
- return this;
- if (this._drag === undefined) {
- let xmax, ymax;
- let x0, y0;
- this._drag = (e) => {
- let x1, y1;
- switch (e.type) {
- case 'mousemove':
- x1 = Math.max(e.clientX, 0);
- y1 = Math.max(e.clientY, 0);
- break;
- case 'touchmove':
- x1 = Math.max(e.changedTouches[0].clientX, 0);
- y1 = Math.max(e.changedTouches[0].clientY, 0);
- break;
- default:
- return;
- }
- const dx = x0 - x1;
- const dy = y0 - y1;
- if (dx == 0 && dy == 0)
- return;
- x0 = x1;
- y0 = y1;
- const w = this._widget;
- const x = Math.max(0, Math.min(xmax, w.offsetLeft - dx));
- const y = Math.max(0, Math.min(ymax, w.offsetTop - dy));
- w.style.left = x + 'px';
- w.style.top = y + 'px';
- this._dragged = true;
- };
- this._startdrag = (e) => {
- switch (e.type) {
- case 'mousedown':
- x0 = e.clientX;
- y0 = e.clientY;
- document.addEventListener('mousemove', this._drag);
- document.addEventListener('mouseup', this._stopdrag);
- e.preventDefault();
- break;
- case 'touchstart':
- x0 = e.touches[0].clientX;
- y0 = e.touches[0].clientY;
- document.addEventListener('touchmove', this._drag);
- document.addEventListener('touchend', this._stopdrag);
- break;
- default:
- return;
- }
- this._dragged = false;
- };
- this._stopdrag = (e) => {
- switch (e.type) {
- case 'mouseup':
- document.removeEventListener('mousemove', this._drag);
- document.removeEventListener('mouseup', this._stopdrag);
- e.preventDefault();
- break;
- case 'touchend':
- document.removeEventListener('touchmove', this._drag);
- document.removeEventListener('touchend', this._stopdrag);
- break;
- default:
- return;
- }
- };
- this._fitin = () => {
- const w = this._widget;
- const cw = this._parent;
- xmax = cw.offsetWidth - w.width;
- ymax = cw.offsetHeight - w.height;
- const x = Math.max(0, Math.min(xmax, w.offsetLeft));
- const y = Math.max(0, Math.min(ymax, w.offsetTop));
- if (x != w.offsetLeft || y != w.offsetTop) {
- w.style.left = x + 'px';
- w.style.top = y + 'px';
- }
- };
- this._dragobserver = new ResizeObserver(this._fitin);
- }
- this._parent.style.position = 'relative';
- this._dragobserver.observe(this._parent);
- this.addEventListener('mousedown', this._startdrag);
- this.addEventListener('touchstart', this._startdrag);
- this.setStyle('position', 'absolute');
- this.setStyle('touchAction', 'none');
- this._draggable = true;
- this._dragged = false;
- return this;
- };
- Draggable.prototype.disableDrag = function() {
- if (!this._draggable)
- return this;
- this._dragobserver.unobserve(this._parent);
- this.removeEventListener('touchstart', this._startdrag);
- this.removeEventListener('mousedown', this._startdrag);
- this.setStyle('touchAction', 'auto');
- this._draggable = false;
- this._dragged = false;
- return this;
- };
Test
- function NoiseClip() {
- ProgramClip.call(this);
- this._interval = NoiseClip.playbackRate;
- this._imageData = null;
- }
- NoiseClip.prototype = Object.create(ProgramClip.prototype);
- Object.defineProperty(NoiseClip.prototype, 'constructor', { value: NoiseClip, enumerable: false, writable: true });
- NoiseClip.playbackRate = 100;
Une instance de NoiseClip hérite de la classe ProgramClip.
La propriété _interval
est héritée de la classe Clip. Elle définit la fréquence de l'animation du clip.
La propriété _imagedata
est un objet ImageData qui contient les données des pixels du canevas de l'image du clip.
- Object.assign(NoiseClip.prototype, Draggable.prototype);
Étend la classe NoiseClip avec la classe Draggable.
- Object.defineProperty(NoiseClip.prototype, 'playbackRate', {
- get: function() {
- return this._playbackRate;
- },
- set: function(r) {
- if (typeof r !== 'number')
- throw new TypeError();
- if (r != NoiseClip.playbackRate)
- throw new RangeError();
- }
- });
Redéfinit l'accesseur playrate
hérité de la classe ProgramClip.
playrate
empêche tout changement de la fréquence de l'animation d'une instance de NoiseClip.
- NoiseClip.prototype.enablePlayer = function() {
- if (this._player)
- return this;
- if (this._click === undefined) {
- this._click = (e) => {
- switch (e.type) {
- case 'click':
- if (this._dragged)
- break;
- if (this._paused)
- this.play();
- else
- this.pause();
- break;
- }
- };
- }
- if (this._keydown === undefined) {
- this._keydown = (e) => {
- e.preventDefault();
- switch (e.key) {
- case ' ':
- if (this._paused)
- this.play();
- else
- this.pause();
- break;
- }
- };
- }
- ProgramClip.prototype.enablePlayer.call(this);
- return this;
- };
Redéfinit la méthode enablePlayer
héritée de la classe Clip.
- NoiseClip.prototype.setWidget = function(w) {
- if (w.tagName != 'CANVAS')
- throw new TypeError();
- if (w.width == 0 || w.height == 0)
- throw new TypeError();
- ProgramClip.prototype.setWidget.call(this, w);
- const ctx = w.getContext('2d');
- const imgdata = ctx.createImageData(w.width, w.height);
- const size = imgdata.width * imgdata.height * 4;
- for (let i = 0; i < size; i += 4)
- imgdata.data[i+3] = 255;
- this._imageData = imgdata;
- window.addEventListener('load', () => this.drawWidget());
- return this;
- };
Redéfinit la méthode setWidget
héritée de la classe Clip.
- NoiseClip.prototype.drawWidget = function() {
- const imgdata = this._imageData;
- const size = imgdata.width * imgdata.height * 4;
- for (let i = 0; i < size; i += 4) {
- imgdata.data[i+0] = Math.random() > 0.5 ? 255 : 0;
- imgdata.data[i+1] = Math.random() > 0.5 ? 255 : 0;
- imgdata.data[i+2] = Math.random() > 0.5 ? 255 : 0;
- }
- const ctx = this._widget.getContext('2d');
- ctx.putImageData(imgdata, 0, 0);
- return this;
- };
Redéfinit la méthode drawWidget
héritée de la classe ProgramClip.
- <?php $size=100; ?>
Définit la taille de l'image du clip, un carré, en pixels.
- <?php $id=uniqid('id'); ?>
Définit l'identifiant de la <div>
qui encadre le HTML du clip.
- #<?php echo $id; ?> {
- min-width: <?php echo $size+20; ?>px;
- min-height: <?php echo $size+20; ?>px;
- max-width: 400px;
- max-height: 200px;
- resize: both;
- overflow: hidden;
- background-color: #fcc;
- background-image: linear-gradient(to right bottom, white 5%, transparent 75%);
- }
- @media screen and (max-width:410px) {
- #<?php echo $id; ?> {
- max-width: 100%;
- }
- }
Définit le CSS de la <div>
qui contient le clip.
- <div id="<?php echo $id; ?>" class="noprint">
- <canvas width="<?php echo $size; ?>" height="<?php echo $size; ?>"></canvas>
- </div>
L'image du clip est dessinée dans un canevas.
- <?php head('javascript', '/objectivejs/Objective.js'); ?>
- <?php head('javascript', '/objectivejs/Responder.js'); ?>
- <?php head('javascript', '/objectivejs/View.js'); ?>
- <?php head('javascript', '/objectivejs/Clip.js'); ?>
- <?php head('javascript', '/objectivejs/ProgramClip.js'); ?>
- <?php head('javascript', '/objectivejs/Draggable.js'); ?>
- <?php head('javascript', '/objectivejs/tests/NoiseClip.js'); ?>
Inclut le code de toutes les classes nécessaires.
RAPPEL : La fonction head
de la librairie iZend ajoute une balise telle que <script src="/objectivejs/Objective.js"></script>
à la section <head>
du document HTML. Adaptez le code à votre environnement de développement.
- const noise = new NoiseClip();
- noise.setManagedWidget(document.querySelector('#<?php echo $id; ?> canvas'));
Crée une instance de NoiseClip et l'associe au canevas. L'image initiale est automatiquement dessinée dès que la fenêtre est complètement chargée.
- noise.enablePlayer();
Active le contrôle de l'animation.
- noise.enableDrag();
Active le contrôle du déplacement du clip.
Commentaires