index.vue 4.14 KB
<!--
 * @Date: 2025-03-10 16:52:35
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-03-13 23:29:32
 * @FilePath: /logic-flow2/src/views/snapshot/index.vue
 * @Description: 导出图片,只能svg,其他类型效果太差
-->
<template>
  <div class="container">
    <div ref="container" class="flow-container"></div>
    <div class="control-panel">
      <el-input v-model="fileName" placeholder="文件名"></el-input>
      <el-select v-model="fileType">
        <el-option label="PNG" value="png" />
        <el-option label="JPEG" value="jpeg" />
        <el-option label="SVG" value="svg" />
      </el-select>
      <el-input-number v-model="width" placeholder="宽度" />
      <el-input-number v-model="height" placeholder="高度" />
      <el-color-picker v-model="backgroundColor" />
      <el-input-number v-model="padding" placeholder="内边距" />
      <el-input-number
        v-model="quality"
        :min="0"
        :max="1"
        :step="0.1"
        placeholder="图片质量"
      />
      <el-checkbox v-model="partial">局部渲染</el-checkbox>

      <el-button @click="downLoad">下载</el-button>
      <el-button @click="previewBlob">预览Blob</el-button>
      <el-button @click="previewBase64">预览Base64</el-button>

      <div v-if="blobData">
        <img :src="blobData" alt="blob preview" />
      </div>
      <div v-if="base64Data">
        <img :src="base64Data" alt="base64 preview" />
      </div>
    </div>
  </div>
</template>

<script setup>
import LogicFlow from '@logicflow/core';
import { Snapshot } from '@logicflow/extension';

const container = ref(null);
let lf = null;

// 状态定义
const fileName = ref('');
const fileType = ref('png');
const width = ref();
const height = ref();
const backgroundColor = ref('white');
const padding = ref();
const quality = ref();
const partial = ref(false);
const blobData = ref('');
const base64Data = ref('');

// 下载方法
const downLoad = async () => {
  const params = {
    fileType: fileType.value,
    backgroundColor: backgroundColor.value,
    partial: partial.value,
    width: width.value,
    height: height.value,
    padding: padding.value,
    quality: quality.value,
  };
  console.log(params, 'params');
  await lf?.getSnapshot(fileName.value, params);
};

// 预览 blob
const previewBlob = () => {
  if (lf) {
    base64Data.value = '';
    lf.getSnapshotBlob(backgroundColor.value, fileType.value)
      .then(({ data, width: w, height: h }) => {
        blobData.value = window.URL.createObjectURL(data);
        console.log('width, height ', w, h);
      });
  }
};

// 预览 base64
const previewBase64 = () => {
  if (lf) {
    blobData.value = '';
    lf.getSnapshotBase64(backgroundColor.value)
      .then(({ data, width: w, height: h }) => {
        base64Data.value = data;
        console.log('width, height ', w, h);
      });
  }
};

onMounted(() => {
  lf = new LogicFlow({
    container: container.value,
    grid: true,
    plugins: [Snapshot],
  });

  lf.on('custom:button-click', (model) => {
    lf.setProperties(model.id, {
      body: 'LogicFlow',
    });
  });

  // 默认开启css样式
  const snapshot = lf.extension.snapshot;
  snapshot.useGlobalRules = true;
  snapshot.customCssRules = `
    .uml-wrapper {
      line-height: 1.2;
      text-align: center;
      color: blue;
    }
  `;

  lf.setTheme({
    rect: {
      fill: "#BDECFF",
      stroke: "#BDEC00",
      strokeWidth: 2,
    },
  });

  lf.render({
    nodes: [
      {
        id: 'node1',
        type: 'rect',
        x: 200,
        y: 100,
      },
      { id: 'node2', type: 'circle', x: 400, y: 100 },
    ],
    edges: [{ id: 'edge1', sourceNodeId: 'node1', targetNodeId: 'node2' }],
  });
  lf.translateCenter();
});
</script>

<style scoped>
.container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.flow-container {
  flex: 1;
  width: 100%;
  height: 100%;
}

.control-panel {
  position: absolute;
  top: 20px;
  left: 20px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  max-width: 80%;
  padding: 16px;
  background: white;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.control-panel > * {
  min-width: 120px;
}
</style>