ホームページ  >  記事  >  ウェブフロントエンド  >  casper.js と like.js に基づいたピクセル比較サービスを実装する

casper.js と like.js に基づいたピクセル比較サービスを実装する

小云云
小云云オリジナル
2018-01-11 09:04:051531ブラウズ

今回は、デザインドラフトとフロントエンドページ間のピクセル比較を提供するノードサービスを共有します。これは、テスターまたはフロントエンド担当者自身が補助テストを完了できるように設計されています。信じてください、ピクセルレベルで比較すると、Web ページ上のデザインドラフトの復元の程度がすぐに明らかになります。以下で言うことはあまりありません。詳細な紹介を見てみましょう。皆さんのお役に立てれば幸いです。

エフェクトプレビュー


前提知識

今回は補助ツールとして次の2つのライブラリを使用します:

  • casperjs: PhantomJSに基づいて書かれています。簡単に言うと、人間をシミュレートしてブラウザを操作する操作を内部的に提供するもので、今回は主にこれを使用します。スクリーンショット機能が付いています。

  • resemble.js: 画像ピクセル比較ツール。呼び出しメソッドを簡単に理解すると、2 つの画像が渡され、差分などの比較パラメータとともに合成画像が返されるということです。基本的な実装のアイデアは、画像をキャンバスに変換し、その画像ピクセルを取得して、各ピクセルを比較することとして理解できます。

つまり、サービス全体の大きなアイデアはすでにあるはずです。それは、casperjs を使用して Web サイトに入り、特定のページをインターセプトし、それを設計図と比較して結果を取得するというものです。

全体的なアイデア

上の図を通して大まかなプロセスを整理できるはずです:

  • フロントエンドからインターセプトする必要があるデザインドラフト画像とWebサイトのアドレスとノード情報を受信します。ページ

  • デザインドラフトを保存します 画像フォルダーに移動します

  • サブプロセスを開始し、casperjsを開始し、ターゲットWebサイトのインターセプトを完了します

  • インターセプト後、form.htmlに画像のアドレス情報を取得し、サーバーに再送信します

  • サーバーは画像を取得しますその情報は、likeejsを通じてデザインドラフトと比較されます

  • 結果はフロントエンドページに返送されます

一部の人が気づくかもしれない問題があります。なぜ casperjs ではターゲット Web サイトのスクリーンショットに情報を直接コピーできないのですか。それをサーバーに戻しますが、フォーム ページを開いてフォームを通じて情報を送信することを選択するのはなぜでしょうか。

A: まず第一に、私は casperjs とノードについてあまり知りません。第一に、casperjs はオペレーティング システムで実行される方法をまだ知りません。 casperjs でノードサービスとの通信を確立します。casper についてあまり詳しくないので、方法があれば教えてください。次に、通信が確立できないため、次善の策に頼るしかありません。casper で作成したフォーム ページをすぐに開き、画像情報を入力してサーバーに送り返すことで、最初のリクエストが完了します。したがって、上記の from.html の操作があります。

実装詳細

簡単な静的サーバーの実装

index.htmlとform.htmlページの返却を伴うため、超簡単な静的サーバーを実装する必要があります。コードは次のとおりです:

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)
    }
   })
  }
 })
}

フォームを解析し、画像フォルダーに画像を保存します

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))
   ...
  } 
 })

読み取り可能なストリームを作成してファイルのコンテンツを読み取り、パイプ経由で指定されたパスに書き込み、アップロードされた画像を保存します。

casperjs を実行します

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

spawn を通じて casperjs を開始する子プロセスを作成できます。また、exec などを使用することもできます。

データを 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()

このコードは比較的単純で、ページを開いて操作を渡し、最後に run を実行します。このプロセス中に、ノード サービスと通信する方法がよくわからなかったので、別のページを開くことにしました。 。さらに詳しく学びたい場合は、非常に詳細な casperjs の公式 Web サイトをチェックしてください。

likee.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)

これにはポイントが含まれます。つまり、現在取得している結果を元のリクエストに返す必要があり、最初のリクエストから現在まで転送されています。これを何度も行ったため、元の戻りボディ解像度が見つかりません。長い間考えた結果、最初のリクエストを受信した後、グローバルオブジェクトを一時的に設定し、リクエスターのIPとタイムスタンプを一意のIDとして設定し、それをオブジェクトのキーとして保存し、その値を現在の値にするだけです。解像度。同時に、id は転送プロセス全体で常に渡され、最後に resObj[id] を呼び出すことによって最初の戻り本体とデータが取得されます。この方法が最適解ではないと思いますが、今は良い方法が思いつかないので、サービス全体を動かすためにはそうするしかありません。 。新しいアイデアがありましたら、ぜひお知らせください。 !

デプロイ

PhantomJS (osx)をインストールします

公式ダウンロード: phantomjs-2.1.1-macosx.zip

解凍パス: /User/xxx/phantomjs-2.1.1-macosx

環境変数を追加します: ~

export PATH="$PATH:/Users/xxx/phantomjs-2.1.1-macosx/bin" を /.bash_profile ファイルに追加します

ターミナル入力: phantomjs --version

バージョン番号が確認できる場合は、インストールは成功しました

casperjsをインストールします

brew update && brew install casperjs

likee.jsをインストールします

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

ノードサービス

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

http://localhost:3033/index.htmlを開きます

関連する推奨事項:

モバイル開発チュートリアルにおけるピクセル表示の問題のまとめ_経験とヒント_Web ページ制作

0.5 ピクセルの境界線を実現する CSS のサンプルコード

解像度、ピクセル、PPI の詳細な紹介

以上がcasper.js と like.js に基づいたピクセル比較サービスを実装するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。