iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 26
0
Modern Web

PixiJS,方便好用的 WebGL 內容產生工具系列 第 26

[PixiJS - Day-26] 實作:PixiJS 也能做功能? 之合圖上傳

PixiJS 不只用來呈現視覺動態,也適合用在一些功能
本篇講的是合圖 / 紙娃娃功能
alt

實作時想法:

Step1. 先用測試的圖片實作功能:
先使用固定的圖片,可以的話再讓使用者自己上傳

Step2. 選到的圖可以拖動、縮放、旋轉:
合圖 / 紙娃娃玩的是調整位置與大小,看起來使用 PixiJS 不難做到

Step3. 匯出與測試:
與後端配合,可以的話串接資料越單純越好

Step4. 讓使用者上傳圖片


由於後端部分由同事製作,因此實作時我的第一步是:
匯出測試

匯出測試用,文字為當下時間
按下Submit按鈕後會存圖開在新視窗裡
alt

var basicText;
var now = new Date();

// 建立一個 PIXI.Text 元件
basicText = new PIXI.Text(getDateString(now));
app.stage.addChild(basicText);

setInterval(
  function(){
    now = new Date();
    // 更新顯示文字
    basicText.text = getDateString(now);
  }, 1000);

// 單純回傳顯示的文字
function getDateString($date){
  return $date.getFullYear()+"/"+
      ($date.getMonth()+1)+"/"+
      $date.getDate()+" "+
      $date.getHours()+":"+
      $date.getMinutes()+":"+
      $date.getSeconds();  
}

匯出部分:

document.getElementById("submit").click = function(){
    submitData();
};
function submitData(){

    // 將圖片存下來
    var dataUrl = app.view.toDataURL("image/jpeg");

	// 目前無法把 data URI 直接開在新視窗
    // window.open(dataUrl);

	// 需用 iframe 的方式
    var iframe = "<iframe width='100%' height='100%' src='" + dataUrl + "' style='margin:0; border:0;'></iframe>"
    var openWindow = window.open();
    openWindow.document.open();
    openWindow.document.write('<html><head><title>Test</title><style>html, body{margin:0;}</style></head><body>');
    openWindow.document.write(iframe);
    openWindow.document.write('</body></html>');
    openWindow.document.close();
}

開啟的視窗是單純的 data URI,圖片上也包含了圖片建立的時間
後端接值時會單純很多
alt

Step1. 可以選擇要放的圖:
回到 Step1,將測試圖片放進場景裡
alt

var bunny = PIXI.Sprite.fromImage('http://pixijs.io/examples/required/assets/basics/bunny.png')
bunny.anchor.set(0.5);
bunny.scale.set(3);
app.stage.addChild(bunny);

Step2. 選到的圖可以拖動、縮放、旋轉:
先處理拖動:

// 設定圖片可互動
bunny.interactive = true;

// 設定圖片在滑鼠滑過時是手勢的形狀
bunny.buttonMode = true;

bunny
  .on('pointerdown', onDragStart)
  .on('pointerup', onDragEnd)
  .on('pointerupoutside', onDragEnd)
  .on('pointermove', onDragMove);

function onDragStart(event) { … };
function onDragEnd(event) { … };
function onDragMove(event) { … };

拖曳部分直接參考官網 DEMOS - Dragging 即可

再處理縮放與旋轉:
這裡使用 dat.GUI
alt

var gui = new dat.GUI();
var bunnyScale = 3;
var bunnyRotate = 0;
var effectController = {
    bunnyScale: bunnyScale,
    bunnyRotate: bunnyRotate
};

gui.add( effectController, "bunnyScale", 0.1, 6, 0.1 ).onChange( guiChange );
gui.add( effectController, "bunnyRotate", -180, 180, 5 ).onChange( guiChange );

function guiChange(){
  bunny.scale.x = effectController.bunnyScale;
  bunny.scale.y = effectController.bunnyScale;
  bunny.rotation = effectController.bunnyRotate* (Math.PI / 180);
}

結合了拖曳、旋轉與縮放,紙娃娃系統幾乎完成了
變形與互動都由 PixiJS 完成,不用計算邊界、不用計算角度
省了很多工

Step3. 匯出與測試
如前文 .toDataURL 的部分

Step4. 使用者選擇圖片:
在 PixiJS裡,將使用者選擇的圖片放進場景也很方便

var sprite = PIXI.Sprite.from(source);

Sprite 類別原始碼

446.    static from(source)
447.    {
448.        return new Sprite(Texture.from(source));
449.    }

而 Texture.from 的方法,在前文讀入材質有提到:
PIXI.Texture.from (source):PIXI.Texture
source number | string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | PIXI.BaseTexture

然後就完成了


為了方便說明,範例少提到一些部分:
拖曳時的中心點:
在 Dragging 範例裡,拖動時是將圖片的中心點直接設定在滑鼠中心
假設拖曳時抓的是圖片的角落,圖片會跳一下
需要將座標移回去

匯出時的BUG:
本文裡的程式碼是:

app.view.toDataURL("image/jpeg");

在 iPhone Safari 可能會遇到問題,如前文

範例解說跟第一張圖不太一樣:
介面部分沒有多說,主要提的是 PixiJS 實作上的功能
使用 dat.GUI 測試


本文用到的一些方法,如有不太清楚的話可以參考先前的文章:


上一篇
[PixiJS - Day-25] 實作:基本繪圖、動態與使用 dat.GUI 測試
下一篇
[PixiJS - Day-27] 實作:第一版萬花筒
系列文
PixiJS,方便好用的 WebGL 內容產生工具31

尚未有邦友留言

立即登入留言