【AdobeXD】プラグイン開発5 WebRequest


![スクリーンショット 2019-01-05 19.27.54.png](https://qiita-image-store.s3.amazonaws.com/0/113504/86bbc9d9-4b25-a625-37d5-b9e90f38fbc7.png "スクリーンショット 2019-01-05 19.27.54.png")

選択したアイテムにランダムな犬の画像を表示するチュートリアル

```howToMakeNetworkRequests.js
const { ImageFill } = require("scenegraph");
const { showDialogY } = require("./dialog.js")

const applyImage = () => {
    const { selection } = require("scenegraph");
    if(selection.items.length) {
        const url = "https://dog.ceo/api/breeds/image/random";
        return fetch(url) // ..(1)
            .then(res => res.json())
            .then(jsonRes => downloadImage(selection, jsonRes));
    }else{
        showDialogY("Please select a shape to apply the downloaded image.");
    }
}

const downloadImage = async (selection, jsonRes) => {
    try{
        const photoUrl = jsonRes.message;
        const photoObj = await xhrBinary(photoUrl); // ..(2)
        const photoObjBase64 = await base64ArrayBuffer(photoObj);
        applyImagefill(selection, photoObjBase64); // ..(3)
    }catch(err){
        showDialogY("error:" + err.message);
    }
}

const xhrBinary = (url) => {
    return new Promise((resolve, reject) => {
        const req = new XMLHttpRequest();
        req.onload = () => {
            if (req.status === 200) {
                try {
                    const arr = new Uint8Array(req.response);
                    resolve(arr);
                } catch (err) {
                    reject('Couldnt parse response. ${err.message}, ${req.response}');
                }
            } else {
                reject('Request had an error: ${req.status}');
            }
        }
        req.onerror = reject;
        req.onabort = reject;
        req.open('GET', url, true);
        req.responseType = "arraybuffer";
        req.send();
    });
}

const applyImagefill = (selection, base64) => {
    const imageFill = new ImageFill(`data:image/jpeg;base64,${base64}`);
    selection.items[0].fill = imageFill;
}

const base64ArrayBuffer = (arrayBuffer) => {
    let base64 = '';
    const encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

    const bytes = new Uint8Array(arrayBuffer);
    const byteLength = bytes.byteLength;
    const byteRemainder = byteLength % 3;
    const mainLength = byteLength - byteRemainder;

    let a;
    let b;
    let c;
    let d;
    let chunk;

    // Main loop deals with bytes in chunks of 3
    for (let i = 0; i < mainLength; i += 3) {
        // Combine the three bytes into a single integer
        chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];

        // Use bitmasks to extract 6-bit segments from the triplet
        a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
        b = (chunk & 258048) >> 12; // 258048   = (2^6 - 1) << 12
        c = (chunk & 4032) >> 6; // 4032     = (2^6 - 1) << 6
        d = chunk & 63;        // 63       = 2^6 - 1

        // Convert the raw binary segments to the appropriate ASCII encoding
        base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
    }

    // Deal with the remaining bytes and padding
    if (byteRemainder === 1) {
        chunk = bytes[mainLength];

        a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2

        // Set the 4 least significant bits to zero
        b = (chunk & 3) << 4; // 3   = 2^2 - 1

        base64 += `${encodings[a]}${encodings[b]}==`;
    } else if (byteRemainder === 2) {
        chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];

        a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
        b = (chunk & 1008) >> 4; // 1008  = (2^6 - 1) << 4

        // Set the 2 least significant bits to zero
        c = (chunk & 15) << 2; // 15    = 2^4 - 1

        base64 += `${encodings[a]}${encodings[b]}${encodings[c]}=`;
    }

    return base64;
}

module.exports = {
    applyImage
}
```

(1) 1度目のWebRequest, GETで犬の画像のURLを取得
(2) 2度目のWebRequest, 画像をとってくる
(3) 画像を選択されたアイテムに反映する。

# ポイント
文字列をとってくるときは`fetch`
画像を取得するときはこのサンプルコピペすればよさそう