summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/blob/sketch/sketch_render.js
blob: ed224824d9f322b32558497e8e44fe3f84008c39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import Vue from 'vue';

export default class SketchRender {
  constructor(browserId, browserPropsId, canvasId, files) {
    this.browserId = browserId;
    this.browserPropsId = browserPropsId;
    this.browserStore = {
      currentPageIndex: 0,
      pages: [],
      activeLayer: '',
      backgroundColor: {
        hex: '#000000',
        rgba: 'rgba(0,0,0,1)'
      },
      hasBackgroundColor: false,
      currentPos: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
      }
    };

    this.files = files;
    if(this.files.hasOwnProperty('document.json')){
      this.files['document.json'].async('string')
       .then(content => this.renderDocument(JSON.parse(content)));
    }

  };

  render() {
    Vue.component('layer', {
      name: 'layer',
      template: 
        `<li class="layer" :class="{artboard: layer._class === 'artboard'}">
          <a href='#' class="expand pull-left" @click.prevent="expand" v-if="layer.layers">
            <span v-if="!expanded">+</span>
            <span v-else>-</span>
          </a>
          <i v-if="layer._class === 'group'" class="fa fa-folder pull-left"></i>
          <i v-if="layer._class === 'text'" class="fa fa-font pull-left"></i>
          <i v-if="layer._class === 'shapeGroup'" class="fa fa-th-large"></i>
          <i v-if="layer._class === 'rectangle'" class="fa fa-square"></i>
          <i v-if="layer._class === 'shapePath'" class="fa fa-heart-o"></i>
          <i v-if="layer._class === 'symbolInstance'" class="fa fa-refresh"></i>
          <i v-if="layer._class === 'symbolMaster'" class="fa fa-refresh"></i>
          <i v-if="layer.isLocked" class="fa fa-lock pull-right"></i>
          <a href='#' @click.prevent="layerSelected(layer)" :title="layer.name">{{layer.name}}</a>
          <ul v-if="layer.layers && expanded">
            <layer :active-layer="activeLayer" :class="{active: activeLayer === layer.do_objectID}" v-for="layer in layer.layers" @layerselected="layerSelected" :key="layer.do_objectID" :layer="layer"></layer>
          </ul>
        </li>`,
      
      props: {
        layer: Object,
        activeLayer: ""
      },

      data() {
        return {
          expanded: false
        }
      },

      methods: {
        expand() {
          this.expanded = !this.expanded;
        },

        layerSelected(layer) {
          this.$emit('layerselected', layer);
        }
      }
    });

    this.vue = new Vue({
      el: `#${this.browserId}`,
      data: this.browserStore,
      computed: {
        currentPage() {
          return this.pages.length ? this.pages[this.currentPageIndex] : {name: 'loading', layers: []};
        }
      },

      methods: {

        rgbToHex(r, g, b) {
          r *= 255;
          g *= 255;
          b *= 255;
          return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
        },

        pageSelected(pageIndex) {
          this.currentPageIndex = pageIndex;
          this.browserStore.currentPos.x = this.browserStore.pages[this.currentPageIndex].frame.x;
          this.browserStore.currentPos.y = this.browserStore.pages[this.currentPageIndex].frame.y;
          this.browserStore.currentPos.width = this.browserStore.pages[this.currentPageIndex].frame.width;
          this.browserStore.currentPos.height = this.browserStore.pages[this.currentPageIndex].frame.height;
        },

        setBackgroundColor(bgColor) {
          if(bgColor){
            this.backgroundColor = this.backgroundColor || {};
            this.backgroundColor.hex = this.rgbToHex(bgColor.red, bgColor.green, bgColor.blue);
            bgColor.red = parseInt(bgColor.red * 255);
            bgColor.green = parseInt(bgColor.green * 255);
            bgColor.blue = parseInt(bgColor.blue * 255);
            this.backgroundColor.rgba = `rgba(${bgColor.red}, ${bgColor.green}, ${bgColor.blue}, ${bgColor.alpha})`
          }
        },

        layerSelected(layer) {
          this.currentPos.x = layer.frame.x;
          this.currentPos.y = layer.frame.y;
          this.currentPos.width = layer.frame.width;
          this.currentPos.height = layer.frame.height;
          this.activeLayer = layer.do_objectID;
          this.hasBackgroundColor = layer.hasBackgroundColor;
          this.setBackgroundColor(layer.backgroundColor);
          console.log('layer._class',layer._class);
          console.log('layer',layer);
        }
      }
    });

    this.vuePos = new Vue({
      el: `#${this.browserPropsId}`,
      data: this.browserStore
    });
  };

  storePage(pageJSON) {
    if(pageJSON){
      var page = JSON.parse(pageJSON);
      page.isActive = false;
      this.browserStore.pages.push(page);
    }
  };

  renderDocument(documentJSON) {
    var pages = documentJSON.pages.map(page => `${page._ref}.json`);
    this.currentPageIndex = documentJSON.currentPageIndex;
    pages.reduce((seq, page) => {
      return seq.then((e) => {
        this.storePage(e);
        return this.files[page].async('string');
      });
    }, Promise.resolve())
      .then((e) => {
        this.storePage(e)
        this.browserStore.currentPos.x = this.browserStore.pages[this.currentPageIndex].frame.x;
        this.browserStore.currentPos.y = this.browserStore.pages[this.currentPageIndex].frame.y;
      });
  };
};