1

我有 svg 渲染场地座位的地方。所有席位都按部门分组。我需要在座位点击事件上,放大该扇区中的那些座位,当我点击另一个扇区时,它应该缩小并再次放大新扇区。这是我想要的一个例子:https ://observablehq.com/@d3/zoom-to-bounding-box?collection=@d3/d3-zoom 。

目前我使用 svgPanZoom.js 库来操作 svg(我知道它使用矩阵而不是 viewBox)。D3 似乎有点难,你能告诉我一个 d3 的替代方案吗?我可以像上面的例子那样做吗?

这是我的代码:

<svg width="100%"
     xmlns="http://www.w3.org/2000/svg"
     ref="venueMap" id="venue-map"
     opacity="1"
     class="seat-map"
     @mousedown.prevent="startDrag"
     @touchstart="startDrag"
     @mousemove="updateEndDragPoint"
     @mouseup="stopDrag"
     @touchend="stopDrag"
     @touchcancel="stopDrag">

  <image :href="layoutImage.url"
         :width="layoutImage.width - (+layoutImage.width * 0.01 * 60)"
         :height="layoutImage.height - (+layoutImage.height * 0.01 * 60)">
  </image>

  <rect
    class="selectArea"
    v-show="shouldDisplaySelectRect"
    :x="dragData.start.x < dragData.end.x ? dragData.start.x : dragData.end.x"
    :y="dragData.start.y < dragData.end.y ? dragData.start.y : dragData.end.y"
    :width="Math.abs(dragData.start.x - dragData.end.x)"
    :height="Math.abs(dragData.start.y - dragData.end.y)">
  </rect>

  <g v-for="(sector,sectorIndex) in placements">
    <g v-for="(row, rowIndex) in sector">
      <rect v-for="(seat, seatIndex) in row"
            :key="seatIndex + 'A'"
            :x="seat.x"
            :y="seat.y"
            :class="seatStyle(seat)"
            class="seat-rect"
            height="9"
            width="9"
            @mouseover="mouseOverSeat(seat, $event)"
            @mouseout="mouseOutFromSeat($event)"
            @click="selectSeat(seat, {sectorIndex, rowIndex}, $event)">
      </rect>
    </g>
  </g>


  <PolygonComponent v-for="(sector, index) in sectors"
                    :key="index"
                    :sector-index="index"
                    :sector="sector"
                    :sector-text-positions="sectorTextPosition">
  </PolygonComponent>

</svg>
4

1 回答 1

0

这是一个简单的缩放示例(Vue + D3 V6

我建议显式传递 SVG 宽度和高度,而不是使用 viewBox:

  const onZoom = (container, event) => container.attr('transform', event.transform);
    
const initView = (ref, width, height) => {    
      // Init SVG container
      const svg = d3.select(ref);
      const container = svg.append('g')
        .classed('container', true);
            
      // Draw something under your container  
      container.append('circle')
        .attr('r', 50)
        .style('fill', '#aaa')
        .style('cursor', 'pointer');
          
      // Init D3 zoom
      const zoom = d3.zoom()
        .scaleExtent([0.5, 10])
        .on('zoom', e => onZoom(container, e));
      svg.call(zoom);
            
      // Center container within SVG    
      const centered = d3.zoomIdentity
        .translate(width/2, height/2);
      svg.call(zoom.transform, centered);  
    }
    
    Vue.component('d3-component', {
      props: ['width', 'height'],
      mounted() {
        initView(this.$refs.svg, this.width, this.height);
      },
      template: '<svg ref="svg" :width="width" :height="height"></svg>'
    })
    
    new Vue({ el: '#d3-zoom-demo' })
    svg {
      background-color: #ccc;
    }
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.2/d3.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="d3-zoom-demo">
  <d3-component width="200" height="150"/>
</div>

于 2021-04-03T08:38:21.950 回答