Maison  >  Article  >  interface Web  >  H5 utilise des composants React pour prendre des photos et sélectionner des images à télécharger

H5 utilise des composants React pour prendre des photos et sélectionner des images à télécharger

不言
不言avant
2018-12-31 09:45:407855parcourir

Le contenu de cet article concerne H5 utilisant des composants React pour prendre des photos et sélectionner des photos à télécharger. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Il y a quelque temps, le projet a été restructuré et transformé en projet SSR, mais le composant de téléchargement de sélection d'images utilisé auparavant ne prenait pas en charge SSR (rendu côté serveur). J’ai donc mené des recherches et trouvé de nombreux outils. Mais certains sont trop gros, certains sont difficiles à utiliser et certains ne répondent pas aux besoins d'utilisation. J'ai décidé d'écrire moi-même un composant de téléchargement d'images mobiles h5. Le téléchargement d’images est une exigence relativement courante. La version PC convient, mais la version mobile n’est pas particulièrement facile à réaliser. Ci-dessous, nous enregistrons brièvement quelques problèmes clés du processus.

Points clés

1. À propos de la saisie

La fonction de sélection est implémentée à l'aide de la balise L'attribut accept='image/*', :capture signifie que le périphérique par défaut du système peut être capturé, tel que : caméra - caméscope --caméra ; microphone - enregistrement. Si capture="camera" est défini, la caméra sera utilisée par défaut. Il y a un problème avec certains modèles qui ne peuvent pas appeler la caméra, nous ne la définirons donc pas ici. Permet plusieurs sélections, plus une fonction de rappel pour l'événement onchange. L'entrée finale ressemblera probablement à ceci :

<input type=&#39;file&#39;
    className={classes.picker}
    accept=&#39;image/*&#39;
    multiple
    capture="camera"
    onChange={this.onfileChange} />

Bien sûr, cette entrée est moche. Nous pouvons l'écraser avec le style de bouton de sélection dont nous avons besoin en définissant `opacity:0` et en le positionnant. Rendez-le un peu plus glamour.

2. À propos de la fonction d'aperçu de la sélection

Pouvoir prévisualiser après avoir sélectionné une image est une fonction courante. Laissons de côté le style ici et ne parlons que de l'implémentation du code. Dans la fonction de rappel d'onchange, nous pouvons obtenir le fichier sélectionné via e.target.files, mais le fichier ne peut pas être affiché sur la page. La méthode habituelle consiste à utiliser reader.readAsDataURL(file) pour le convertir en base64 puis à l'afficher. sur la page supérieure. J'utilise ici une grille de neuf carrés, et chaque image est une toile. Compte tenu du problème des différents formats d'image, j'obtiens d'abord le fichier base64 via reader.readAsDataURL(file). Créez ensuite une image dessinée à travers les proportions du canevas de la grille à neuf carrés, afin que le contenu de l'image puisse couvrir l'intégralité du canevas sans distorsion.

fileToCanvas (file, index) {//文件
        let reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = (event) => {
            let image = new Image();
            image.src = event.target.result;
            image.onload = () => {
                let imageCanvas = this['canvas' + index].getContext('2d');
                let canvas = { width: imageCanvas.canvas.scrollWidth * 2, height: imageCanvas.canvas.scrollHeight * 2 };
                let ratio = image.width / image.height;
                let canvasRatio = canvas.width / canvas.height;
                let xStart = 0; let yStart = 0; let renderableWidth; let renderableHeight;
                if (ratio > canvasRatio) { 
                // 横向过大,以高为准,缩放宽度
                    let hRatio = image.height / canvas.height;
                    renderableHeight = image.height;
                    renderableWidth = canvas.width * hRatio;
                    xStart = (image.width - renderableWidth) / 2;
                }
                if (ratio < canvasRatio) { 
                // 横向过小,以宽为准,缩放高度
                    let wRatio = image.width / canvas.width;
                    renderableWidth = image.width;
                    renderableHeight = canvas.height * wRatio;
                    yStart = (image.height - renderableHeight) / 2;
                }
                imageCanvas.drawImage(image, xStart, yStart, renderableWidth, renderableHeight, 0, 0, canvas.width * 2, canvas.height);
            };
        };
    }

3. Obtenez l'extension du fichier téléchargé

Lors de la prise de photos sur certains modèles, le fichier obtenu via l'événement onchange est blob (Xiaomi 6, etc.) À cette fois, via blob.type Déterminez manuellement l'extension.

4. Obtenir la direction de prise de photos avec iOS

Lorsque l'image iOS est téléchargée, il s'avère que le fichier local a été pivoté. La raison en est en effet normale. le problème ne sera pas expliqué en détail ici. Si vous êtes intéressé, vous pouvez le rechercher. Nous devons donc détecter l'orientation et faire pivoter l'image vers son orientation normale. Il existe de nombreuses bibliothèques prêtes à l'emploi pour s'orienter, comme Exif.js. Mais cette bibliothèque est un peu volumineuse, et cela ne semble pas valoir la peine de l’introduire pour cette petite exigence. Il existe de nombreux codes prêts à l'emploi pour obtenir la direction de l'image sur stackoverflow.
Légèrement modifié :

getOrientation (file) {
        return new Promise((resolve, reject) => {
            let reader = new FileReader();
            reader.onload = function (e) {
            //e.target.result为base64编码的文件
                let view = new DataView(e.target.result);
                if (view.getUint16(0, false) !== 0xffd8) {
                    return resolve(-2);
                }
                let length = view.byteLength;
                let offset = 2;
                while (offset < length) {
                    let marker = view.getUint16(offset, false);
                    offset += 2;
                    if (marker === 0xffe1) {
                        let tmp = view.getUint32(offset += 2, false);
                        if (tmp !== 0x45786966) {
                            return resolve(-1);
                        }
                        let little = view.getUint16(offset += 6, false) === 0x4949;
                        offset += view.getUint32(offset + 4, little);
                        let tags = view.getUint16(offset, little);
                        offset += 2;
                        for (let i = 0; i < tags; i++) {
                            if (view.getUint16(offset + i * 12, little) === 0x0112) {
                                return resolve(view.getUint16(offset + i * 12 + 8, little));
                            }
                        }
                    } else if ((marker & 0xff00) !== 0xff00) {
                        break;
                    } else {
                        offset += view.getUint16(offset, false);
                    }
                }
                return resolve(-1);
            };

            reader.readAsArrayBuffer(file.slice(0, 64 * 1024));
        });
    }

//Valeur de retour : 1--normal, -2--non-jpg, -1--indéfini

5.ios direction de la photo Correction

L'orientation normale de l'image doit être 1, nous convertissons donc le fichier en canevas et utilisons la méthode de transformation de canevas pour transformer le canevas, veuillez vous y référer. Enfin, récupérez l'image base64 avec la direction normale du codage base64 via canvas.toDataURL(''), puis convertissez la base64 en blob pour le téléchargement

    //重置文件orientation
resetOrientationToBlob (file, orientation) {
    return new Promise((resolve, reject) => {
        let reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = (event) => {
            let image = new Image();
            image.src = event.target.result;
            image.onload = () => {
                let width = image.width;
                let height = image.height;
                let canvas = document.createElement('canvas');
                let ctx = canvas.getContext('2d');
                if (orientation > 4 && orientation < 9) {
                    canvas.width = height;
                    canvas.height = width;
                } else {
                    canvas.width = width;
                    canvas.height = height;
                }

                switch (orientation) {
                case 2:
                    ctx.transform(-1, 0, 0, 1, width, 0);
                    break;
                case 3:
                    ctx.transform(-1, 0, 0, -1, width, height);
                    break;
                case 4:
                    ctx.transform(1, 0, 0, -1, 0, height);
                    break;
                case 5:
                    ctx.transform(0, 1, 1, 0, 0, 0);
                    break;
                case 6:
                    ctx.transform(0, 1, -1, 0, height, 0);
                    break;
                case 7:
                    ctx.transform(0, -1, -1, 0, height, width);
                    break;
                case 8:
                    ctx.transform(0, -1, 1, 0, 0, width);
                    break;
                default:
                    ctx.transform(1, 0, 0, 1, 0, 0);
                }

                ctx.drawImage(image, 0, 0, width, height);
                let base64 = canvas.toDataURL('image/png');
                let blob = this.dataURLtoBlob(base64);
                resolve(blob);
            };
        };
    });
}

Enfin

Téléchargement d'images, cette partie devrait être relativement simple. Téléchargez simplement le fichier sous la forme de FormData. Le code ci-dessus n'est que le pseudo-code de certaines fonctions et ne constitue pas l'implémentation finale de toutes les fonctions.

Essayez-le si vous le pouvez. Au final, vous constaterez que vous avez beaucoup appris, mais les roues des autres sont encore plus utiles 2333.


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer