Pixo with Custom Controls

by pixoeditor

HTML

<script src="https://pixoeditor.com/editor/scripts/bridge.m.js"></script>
   <h2>Pixo Editor with Custom Controls</h2>
   <button id="custom_editor_opener">Open</button>
   
   <div id="custom_editor" style="display: none;">
      <div id="custom_editor_controls">
         <button id="custom_editor_draw">Draw</button>
         <button id="custom_editor_crop">Crop</button>
         |
         <button id="custom_editor_undo">Undo</button>
         <button id="custom_editor_redo">Redo</button>
      </div>
      <div id="custom_editor_draw_properties" style="display: none;">
         Line width:
         <input type="range" id="custom_editor_draw_width" min="0" max="150" step="1" />
         Color:
         <input type="color" id="custom_editor_draw_color" />
         Opacity:
         <input type="range" id="custom_editor_draw_opacity" min="0" max="1" step="0.01" />
      </div>
      <div id="custom_editor_placeholder"></div>
   </div>

CSS

body { 
  height: 450px;
  max-height: 100vh;
}

#custom_editor {
  display: flex;
  flex-direction: column;
  height: 100vh;
}
#custom_editor_controls {
  padding: 10px;
}
#custom_editor_placeholder {
  flex: 1;
}

JavaScript

function destructureRGBA(color) {
  if (!/^rgba/.test(color)) {
    return { color, opacity: 1 };
  }
  const match = color.match(/^rgba\(([\d\s,]+),\s*([\.\d]+)\s*\)/);
  return {
    color: '#' + match[1]
    .split(',')
    .map(x => Number(x.trim()).toString(16).padStart(2, 0))
    .join(''),
    opacity: match[2],
  };
}

function hexToRGBA(hex, opacity = 1) {
  const bigint = parseInt(hex.substr(1), 16);
  const r = (bigint >> 16) & 255;
  const g = (bigint >> 8) & 255;
  const b = bigint & 255;

  return `rgba(${r}, ${g}, ${b}, ${opacity})`;
}

custom_editor_opener.onclick = function () {
  custom_editor.style.display = '';
  const el = this;
  const state = {};
  const pixo = new Pixo.Bridge({
    apikey: '26uqyj79pdgk',
    type: 'child',
    parent: 'custom_editor_placeholder',
    styles: {
      css: '.pixo-editmenu, .pixo-actionsmenu, .pixo-propertypanel { display: none }',
    },
    onSave: function (data) {
      el.parentNode.insertBefore(data.toImage(), el);
    },
    onClose: function () {
      custom_editor.style.display = 'none';
    },
    onStateChange: function (s) {
      Object.assign(state, s);
      const { active_plugin, history, plugins: { draw } } = state;

      custom_editor_undo.disabled = !history.current;
      custom_editor_redo.disabled = history.current === history.length - 1;

      custom_editor_draw_width.value = draw.linewidth;

      const { color, opacity } = destructureRGBA(draw.linecolor);
      custom_editor_draw_color.value = color;
      custom_editor_draw_opacity.value = opacity;

      custom_editor_draw_properties.style.display = active_plugin === 'draw'
        ? '' : 'none';
    },
  });
  pixo.edit('https://via.placeholder.com/320x240.jpg');
  pixo
    .exec('ACTIVATE_PLUGIN', { plugin: 'draw' })
    .exec('SET_DRAWING_PROPERTY', { propname: 'brushmode', value: 'Pencil' })
    .exec('SET_DRAWING_PROPERTY', { propname: 'shadowwidth', value: 0 });

  custom_editor_draw.onclick = function () {
   ...