Maison >interface Web >js tutoriel >Implémenter un service de comparaison de pixels basé sur casper.js et similar.js

Implémenter un service de comparaison de pixels basé sur casper.js et similar.js

小云云
小云云original
2018-01-11 09:04:051571parcourir

Cette fois, je partage un service de nœud qui permet une comparaison de pixels entre les brouillons de conception et les pages frontales. Il est conçu pour effectuer un test auxiliaire pour les testeurs ou le personnel front-end lui-même. Croyez-moi, lors de la comparaison au niveau des pixels, le degré de restauration du projet de conception sur la page Web deviendra immédiatement apparent. Pas grand chose à dire ci-dessous, jetons un œil à l'introduction détaillée, j'espère que cela pourra aider tout le monde.

Aperçu de l'effet


Pré-connaissances

Les deux bibliothèques suivantes sont utilisées cette fois comme outils auxiliaires :

  • casperjs : écrit basé sur PhantomJS. Il fournit un navigateur sans interface en interne. En termes simples, vous pouvez l'utiliser pour compléter l'opération de simulation d'un humain pour faire fonctionner le navigateur sous forme de code, ce qui implique divers événements de souris et de nombreuses autres fonctions. Cette fois, il est principalement utilisé. est livré avec une fonction de capture d'écran.

  • resemble.js : outil de comparaison de pixels d'image. La simple compréhension de la méthode appelante est que deux images sont transmises et qu'une image composite est renvoyée avec des paramètres de comparaison tels que la différence, etc. L'idée de base de la mise en œuvre peut être comprise comme la conversion de l'image en toile, l'obtention de ses pixels d'image, puis la comparaison de chaque pixel.

Nous devrions donc déjà avoir une grande idée pour l'ensemble du service, qui consiste à utiliser casperjs pour accéder à un site Web afin d'intercepter une page, puis à la comparer avec le dessin de conception pour obtenir le résultat.

Idée générale

À partir de l'image ci-dessus, nous devrions être en mesure de trier un processus approximatif :

  • Depuis le front-end, la page reçoit les images du brouillon de conception, ainsi que l'adresse du site Web et les informations sur le nœud qui doivent être interceptées

  • Enregistrez le brouillon de conception dans le dossier d'images

  • Ouvrez le sous-processus, démarrez casperjs et terminez l'interception du site Web cible

  • Après l'interception, demandez form.html pour remplir les informations d'adresse de l'image et re- retransmettez-le au serveur

  • Le serveur obtient les informations sur l'image et compare la capture d'écran avec le brouillon de conception via similarjs

  • Le résultat est envoyé retour à la page d'accueil

Il y a un problème avec cela. Quelqu'un l'a peut-être remarqué : Pourquoi ne puis-je pas renvoyer directement les informations au serveur lorsque je prends une capture d'écran du site Web cible dans casperjs ? Au lieu de cela, je choisis d'ouvrir une page de formulaire pour soumettre les informations via le formulaire ?

R : Tout d'abord, je ne connais pas grand-chose à Casperjs et à Node. Ce que je comprends, c'est que tout d'abord, Casperjs n'est pas un module de noeud, il s'exécute dans le système d'exploitation que je n'ai pas encore. J'ai découvert comment créer un lien avec Casperjs dans Casperjs. S'il existe un moyen de communiquer avec le service de nœud, dites-le-moi, car je ne connais vraiment pas grand-chose à Casper ! Deuxièmement, comme la communication ne peut pas être établie, je ne peux que recourir à la meilleure solution, ouvrir rapidement une page de formulaire que j'ai écrite via Casper, remplir les informations de l'image et la renvoyer au serveur. Cela peut compléter la demande initiale. Il y a donc l’opération ci-dessus from.html.

Détails d'implémentation

Implémentation d'un serveur statique simple

Parce que cela implique le retour des pages index.html et form.html, il est nécessaire de implémentez un serveur statique super simple. Le code est le suivant :

const MIME_TYPE = {
 "css": "text/css",
 "gif": "image/gif",
 "html": "text/html",
 "ico": "image/x-icon",
 "jpeg": "image/jpeg",
 "jpg": "image/jpg",
 "js": "text/javascript",
 "json": "application/json",
 "pdf": "application/pdf",
 "png": "image/png",
 "svg": "image/svg+xml",
 "swf": "application/x-shockwave-flash",
 "tiff": "image/tiff",
 "txt": "text/plain",
 "wav": "audio/x-wav",
 "wma": "audio/x-ms-wma",
 "wmv": "video/x-ms-wmv",
 "xml": "text/xml"
}
function sendFile(filePath, res) {
 fs.open(filePath, 'r+', function(err){ //根据路径打开文件
  if(err){
   send404(res)
  }else{
   let ext = path.extname(filePath)
   ext = ext ? ext.slice(1) : 'unknown'
   let contentType = MIME_TYPE[ext] || "text/plain" //匹配文件类型
   fs.readFile(filePath,function(err,data){
    if(err){
     send500(res)
    }else{
     res.writeHead(200,{'content-type':contentType})
     res.end(data)
    }
   })
  }
 })
}

Analyser le formulaire et stocker les images dans le dossier images

const multiparty = require('multiparty') //解析表单
let form = new multiparty.Form()
 form.parse(req, function (err, fields, files) {
  let filename = files['file'][0].originalFilename,
   targetPath = __dirname + '/images/' + filename,
  if(filename){
   fs.createReadStream(files['file'][0].path).pipe(fs.createWriteStream(targetPath))
   ...
  } 
 })

Lire le contenu du fichier en créant un flux lisible, puis écrivez-le dans le Les images téléchargées peuvent être enregistrées sous le chemin spécifié.

Exécuter Casperjs

const { spawn } = require('child_process')
spawn('casperjs', ['casper.js', filename, captureUrl, selector, id])
casperjs.stdout.on('data', (data) => {
 ...
})

Vous pouvez créer un sous-processus pour démarrer Casperjs via spawn, vous pouvez également utiliser exec, etc.

Prenez une capture d'écran et soumettez les données à form.html

const system = require('system')
const host = 'http://10.2.45.110:3033'
const casper = require('casper').create({
 // 浏览器窗口大小
 viewportSize: {
  width: 1920,
  height: 4080
 }
})
const fileName = decodeURIComponent(system.args[4])
const url = decodeURIComponent(system.args[5])
const selector = decodeURIComponent(system.args[6])
const id = decodeURIComponent(system.args[7])
const time = new Date().getTime()
casper.start(url)
casper.then(function() {
  console.log('正在截图请稍后')
  this.captureSelector('./images/casper'+ id + time +'.png', selector)
})
casper.then(function() {
 casper.start(host + '/form.html', function() {
  this.fill('form#contact-form', {
   'diff': './images/casper'+ id + time +'.png',
   'point': './images/' + fileName,
   'id': id
  }, true)
 })
})
casper.run()

Le code est relativement simple. Le processus principal consiste à ouvrir une page, puis à transmettre votre opération. , et enfin Exécuter run. Au cours de ce processus, je ne savais pas trop comment communiquer avec le service de nœud, j'ai donc choisi d'ouvrir une autre page. . Si vous souhaitez étudier en profondeur, vous pouvez consulter le site officiel de casperjs qui est très détaillé !

Effectuer une comparaison de pixels et renvoyer des données via similar.js

function complete(data) {
  let imgName = 'diff'+ new Date().getTime() +'.png',
   imgUrl,
   analysisTime = data.analysisTime,
   misMatchPercentage = data.misMatchPercentage,
   resultUrl = './images/' + imgName
  fs.writeFileSync(resultUrl, data.getBuffer())
  imgObj = {
   ...
  }
  let resEnd = resObj[id] // 找回最开始的res返回给页面数据
  resEnd.writeHead(200, {'Content-type':'application/json'})
  resEnd.end(JSON.stringify(imgObj))
 }
let result = resemble(diff).compareTo(point).ignoreColors().onComplete(complete)

Cela implique un point, c'est-à-dire que les résultats que j'obtiens maintenant doivent être renvoyés à la demande d'origine, et j'ai été redirigé plusieurs fois depuis la demande initiale jusqu'à maintenant, ce qui fait que je ne trouve plus ma résolution de corps de retour d'origine. Après y avoir longuement réfléchi, je ne peux définir que temporairement l'objet global. Après avoir reçu la demande initiale, définir l'adresse IP et l'horodatage du demandeur comme identifiant unique et le stocker comme clé de l'objet, et la valeur est la valeur actuelle. rés. Dans le même temps, l'identifiant est transmis à tout moment pendant tout le processus de transfert, et finalement le corps et les données de retour initiaux sont obtenus en appelant resObj[id]. Je ne pense pas que cette méthode soit la solution optimale, mais comme je ne trouve pas de bonne méthode pour le moment, je dois la faire afin de parcourir l'ensemble du service. . Si vous avez de nouvelles idées, n'hésitez pas à nous en faire part ! !

Déploiement

Installer PhantomJS (osx)

Téléchargement du site officiel : phantomjs-2.1.1-macosx.zip

Décompression chemin :/User/xxx/phantomjs-2.1.1-macosx

Ajouter des variables d'environnement : ajoutez

export PATH="$PATH:/Users/xxx/phantomjs- dans le ~/. bash_profile file 2.1.1-macosx/bin"

Entrée du terminal : phantomjs --version

Si vous pouvez voir le numéro de version, l'installation est réussie

Installez casperjs

brew update && brew install casperjs

Installez similar.js

cnpm i resemblejs //已写进packjson可不用安装
brew install pkg-config cairo libpng jpeg giflib
cnpm i canvas //node内运行canvas

service de nœud

git clone https://github.com/Aaaaaaaty/gui-auto-test.git
cd gui-auto-test
cnpm i
cd pxdiff
nodemon server.js

Ouvrez http://localhost :3033/index.html

Recommandations associées :

Résumé des problèmes d'affichage des pixels dans les tutoriels de développement mobile_Expériences et astuces_Production de pages Web

Exemple de code pour l'implémentation CSS d'une bordure de 0,5 pixel

Introduction détaillée à la résolution, aux pixels et au PPI

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn