Sau một thời gian sử dụng và tìm hiểu, tôi có thêm trải nghiệm với G6. Bài viết này chủ yếu giới thiệu các chức năng nhỏ sau.
- 1. Bố cục cơ bản và cách sử dụng sơ đồ cây
- 2. Tùy chỉnh các kiểu nút khác nhau theo các thuộc tính khác nhau của dữ liệu được trả về.
- 3. Khi bản sao nhãn nút quá dài, nó sẽ được hiển thị thông qua việc cắt bớt...
- 4. Khi nút cha chứa các nút lá con, độ dài của nút con được hiển thị sau nhãn. Định dạng là: node.label(children.length)
- 5. Nhãn bị cắt cụt được hiển thị hoàn toàn trong chú giải công cụ bằng cách di chuột vào nó. Xác định và viết lại kiểu chú giải công cụ.
- 6. Tự động thay đổi vị trí hiển thị nhãn theo trạng thái mở rộng và thu gọn của nút. Nó ở trên cùng khi được mở rộng và ở bên phải khi thu gọn.
- 7. Đặt kiểu biểu tượng và màu nền của nút (màu ngẫu nhiên có thể được tùy chỉnh)
- 8. Nếu có nhiều hơn (xxx) nút lá, hãy thu gọn các nút lá đó và hiển thị các nút lá được mở rộng hơn.
- 9. Nhấp để mở rộng thêm các nút và hiển thị các nút lá đã thu gọn.
- 10. Xác định sự kiện nhấp chuột và tập trung nút hiện được nhấp vào điểm giữa của khung vẽ
- 11. Xác định sự kiện di chuyển chuột vào và ra
- 12. Tùy chỉnh các kiểu cạnh khác nhau theo các thuộc tính khác nhau của dữ liệu được trả về.
- 13. Đặt kiểu sao chép mối quan hệ trên đường kết nối
- 14. Giải quyết vấn đề dư ảnh đen khi kéo canvas
- 15. Trình diễn hoạt hình demo
- 16. Hoàn thành trường hợp Demo
1. Bố cục cơ bản và cách sử dụng sơ đồ cây
Đối với bố cục sơ đồ cây, mẫu được sử dụng là mẫu cây nhỏ gọn do trang web chính thức cung cấp. Trên cơ sở này, một số sửa đổi tùy chỉnh được thực hiện, như được hiển thị trong trường hợp cây nhỏ gọn của trang web chính thức.
Mô tả tài sản:
graph = new G6.TreeGraph({ container, width: document.documentElement.clientWidth, Height:document.documentElement.clientHeight, //..... bố cục: { type: 'compactBox', // Hướng kiểu bố cục: 'LR ', // Hướng bố cục bản đồ cây, từ trái sang phải getHeight: function getHeight() { // Trả về chiều cao 16 }, getWidth: function getWidth() { // Chiều rộng trả về 16 }, getVGap: function getVGap() { // Khoảng cách dọc giữa các nút trả về 25 }, getHGap: function getHGap() { // Khoảng cách ngang giữa các nút trả về 150 } } })
2. Tùy chỉnh các kiểu nút khác nhau theo các thuộc tính khác nhau của dữ liệu được trả về.
Trong hầu hết các dự án thực tế, dữ liệu được trả về từ phần phụ trợ. Có thể có nhiều loại dữ liệu yêu cầu xử lý và hiển thị khác nhau. Tại thời điểm này, rõ ràng là chỉ xác định defaultNode trong quá trình khởi tạo biểu đồ. Cần phải sau khi khởi tạo biểu đồ:
// Các hàm sau có mã triển khai bên dưới: graph.node((node)=> { return { label: node.label || formatLabel(node), icon: formatIcon(node), size: node.size || 40 , labelCfg: { vị trí: setLabelPos(node) }, // kiểu vị trí hiển thị nhãn: { fill: getNodeColor(), đột quỵ: getNodeColor() } } })
3. Khi bản sao nhãn nút quá dài, nó sẽ được hiển thị thông qua việc cắt bớt...
Đầu tiên, nó đánh giá xem nút hiện tại có nút con hay không, sau đó nhãn sẽ được ghép để hiển thị số lượng nút lá khi kết thúc quá trình, vì lý do dữ liệu trong cuốn sách này, nhãn dữ liệu và id. trong trường hợp sử dụng trường tương tự Sau này, học sinh có thể nhấn Điều chỉnh tùy theo tình hình thực tế: độ dài tôi chặn là 15.
// nhãn Định dạng thẻ... const formatLabel = (node) => { const hasChildren = node.childrenBak?.length || node.children?.length const ellipsis = node.id.length > 15 ? '...' : '' return `${node.id.slice(0, 15)}${ellipsis}${hasChildren ? ' (' + hasChildren + ')' : ''}` }
4. Khi nút cha chứa các nút lá con, độ dài của nút con được hiển thị sau nhãn. Định dạng là: node.label(children.length)
Hàm nhỏ này, được cắt bớt khỏi nhãn trước đó, xử lý các nhãn theo cách tương tự, do đó, nó được trả về trong cùng một hàm. Mã triển khai chính của nó là dòng này:
trả về `${node.id.slice(0, 15)}${ellipsis}${hasChildren ? ' (' + hasChildren + ')' : ''}`
Có rất nhiều thay đổi trong thiết kế của chức năng nhỏ này. Học sinh đừng nhầm lẫn.
Bước 1: Đầu tiên hãy xác định một hàm và trả về chú giải công cụ. Trong trường hợp trang web chính thức, đó không phải là một hàm được trả về mà là một đối tượng được trả về trực tiếp. Điều này sẽ gây ra vấn đề trong quá trình sử dụng thực tế, tức là dữ liệu mới được thêm vào không thể được. được sử dụng trong plug-in này, vì vậy hiện tượng này có thể được giải quyết bằng cách gọi hàm:
// Khi nhãn hiển thị..., display tip const treeTooltip = ()=> { return new G6.Tooltip({ offsetX: 10, // mouse offset offsetY: 20, ShouldBegin(e: Any) { return e .item? .get('model')?.label?.includes('...') // Chỉ hiển thị nếu có... trong nhãn, nghĩa là nó bị cắt bớt}, getContent(e: Any) { let outDiv = document.createElement('div') // Đặt vùng chứa mẹo và kiểu outDiv.innerHTML = ` ${e.item.getModel().id}
` trở lại outDiv }, itemTypes: ['node'] // Cho biết loại phần tử được kích hoạt }) }
Bước 2: Thêm cách sử dụng plug-in trong các tùy chọn được tạo mới.
đồ thị = new G6.TreeGraph({ container, chiều rộng: document.documentElement.clientWidth, chiều cao:document.documentElement.clientHeight, plugin: [treeTooltip()], // ..... })
Bước 3: Sau khi hoàn thành đoạn mã trên, về cơ bản bạn có thể thấy hộp nhắc nhở mẹo. Tuy nhiên, do kiểu ban đầu được viết lại nên bạn cũng cần thay đổi kiểu vì có nhiều thao tác trên canvas, canvas canvas và kiểu chuột. đã được sửa đổi Toàn văn chỉ có các sửa đổi về Phong cách được đề cập ở đây. Chỉ viết chung thôi chứ thực tế nó không ảnh hưởng gì đến chức năng tooltip.
6. Tự động thay đổi vị trí hiển thị nhãn theo trạng thái mở rộng và thu gọn của nút. Nó ở trên cùng khi được mở rộng và ở bên phải khi thu gọn.
Chức năng này được thiết kế để tối ưu hóa Khi nhãn nút quá dài và được mở rộng, các vấn đề như chồng chéo bản sao sẽ xảy ra khi khoảng cách theo chiều ngang giữa nút gốc và nút con không đủ.
Đầu tiên, xác định xem nút có ở trạng thái mở rộng hay không và có nút lá hay không. Khi nút có con và được mở rộng, các trường hợp còn lại sẽ được hiển thị ở bên phải.
// Tự động thay đổi vị trí hiển thị nhãn theo trạng thái mở rộng và thu gọn của nút. Nó ở trên cùng khi được mở rộng và ở bên phải khi thu gọn const setLabelPos = (node) => { return !node.collapsed && node.children. ?.length ? 'top' : 'đúng' }
Vì bản đồ cây có thể giám sát trạng thái mở rộng và thu gọn của nút nên khi chuyển đổi cũng cần thực hiện định vị nhãn: thêm các chế độ vào các tùy chọn của quá trình khởi tạo mới.
graph = new G6.TreeGraph({ container, width: document.documentElement.clientWidth, height:document.documentElement.clientHeight, plugins: [treeTooltip()], // ..... modes: { default: [ { type: 'collapse-expand', onChange: function onChange(item: any, collapsed) { const data = item?.get('model') data.collapsed = collapsed const model = { id: data.id, labelCfg: { position: !collapsed ? 'top' : 'right' } } item.update(model) item.refresh() return true } }, 'drag-canvas', 'zoom-canvas' ] } })
7. Đặt kiểu biểu tượng và màu nền của nút (màu ngẫu nhiên có thể được tùy chỉnh)
Không cần phải dài dòng nữa, hãy xử lý biểu đồ biểu tượng của nút. Biểu đồ có thể sử dụng hình ảnh hoặc văn bản. Ở đây chúng tôi sử dụng văn bản. Chúng tôi chặn hai chuỗi đầu tiên của nhãn và đặt màu nền (màu ngẫu nhiên có thể được tùy chỉnh).
// Xử lý biểu tượng nút lá chặn hai chuỗi đầu tiên của ID const formatIcon = (node) => { node.icon = { text: node.id.slice(0,2), fill: '#fff', Stroke: ' #fff', textBaseline: 'middle', fontSize: 20, width: 25, Height: 25, show: true } } // Màu nền của các nút lá được điền ngẫu nhiên const getNodeColor = () => { const màu = ["#8470FF", "#A020F0", "#C0FF3E", "#FF4500", "#66d6d1"]; trả về màu sắc[Math.floor(Math.random() *. chiều dài)]; }
8. Nếu có nhiều hơn (xxx) nút lá, hãy thu gọn các nút lá đó và hiển thị các nút lá được mở rộng hơn.
Khi có nhiều nút lá, bạn không muốn mở rộng tất cả, thay vào đó, bạn chỉ hiển thị một phần của chúng trước và các nút khác được xếp vào nút mở rộng. Để thực hiện ý tưởng, hãy xác định một thuộc tính để chấp nhận tất cả. con ban đầu, sau đó chặn nó và nhấn nút mở rộng để triển khai nó:
Bước 1: Xác định thuộc tính ChildrenBak để chấp nhận dữ liệu con.
// Không có gì xảy ra, hãy sử dụng hàm const splitChild = (node) => { node.childrenBak = node.children ? [...node.children] : [] let result: any = [] if(node.children){ result = node.children.slice(0, 5) if (node.children.length > 5) { result.push({ id: `Expand-${node.id}`, label: ' Mở rộng thêm...' }) } node.children = result node.children.forEach(child =>{ splitChild(child) }) } }
9. Nhấp để mở rộng thêm các nút và hiển thị các nút lá đã thu gọn.
Bước 2: (Tiếp tục với chức năng 8) Khi bạn nhấp để mở rộng thêm, các nút thu gọn còn lại sẽ được hiển thị và sự kiện nút: nhấp chuột sẽ được xác định.
Ý tưởng: Tìm thêm nút để mở rộng, tìm nút cha để mở rộng thêm nút và cập nhật nút con của nút cha.
graph.on('node:click', (evt) => { const { item } = evt const node = item?.get('model') if (node.id.includes('Expand')) { // Chứa Mở rộng trong id có nghĩa là mở rộng thêm const parentNode = graph.getNeighbors(item, 'source')[0].get('model') // Tìm nút cha mở rộng nhiều nút hơn graph.updateChildren(parentNode.childrenBak, parentNode.id) // Cập nhật nút con của nút cha bằng cách sử dụng ChildrenBak được khai báo ở bước trước } })
10. Xác định sự kiện nhấp chuột và tập trung nút hiện được nhấp vào điểm giữa của khung vẽ
Xiao 9 đã đề cập đến sự kiện nhấp chuột, do đó, có một điểm tối ưu hóa nhỏ khác trong sự kiện nhấp chuột, đó là di chuyển nút hiện được nhấp vào giữa khung vẽ và tạo kiểu lựa chọn nổi bật cho nó.
const animateCfg = { thời lượng: 200, giảm bớt: 'easeCubic' } graph.on('node:click', (evt) => { const { item } = evt const node = item?.get('model') // if (node.id.includes('Expand')) { // Mã điểm hàm 9 // const parentNode = graph.getNeighbors(item, 'source')[0].get('model') // console.log(parentNode,parentNode.childrenBak); // graph.updateChildren(parentNode.childrenBak, parentNode.id) // } setTimeout(() => { if (!node.id.includes('Expand')) { graph.focusItem(item, true, animateCfg) graph.getNodes().forEach((node) => { graph.clearItemStates(node) // Xóa kiểu tô sáng của các nút khác trước}) graph.setItemState(item, 'selected', true) // cần phải được chọn trong ví dụ } }, 500) })
được chọn đại diện cho nodeStateStyles, là kiểu trạng thái nút.
graph = new G6.TreeGraph({ container, width: document.documentElement.clientWidth, Height:document.documentElement.clientHeight, plugin: [treeTooltip()], //..... nodeStateStyles: { active: { // this Được sử dụng để di chuột, bạn có thể xác định fill: 'l(0) 0:#FF4500 1:#32CD32', đột quỵ: 'l(0) 0:#FF4500 1:#32CD32', lineWidth: 5 }, selected: { // Cái này được sử dụng để chọn chuột, bạn có thể tự xác định nó fill: 'l(0) 0:#FF4500 1:#32CD32', đột quỵ : ' l(0) 0:#FF4500 1:#32CD32', lineWidth: 5 } } })
11. Xác định sự kiện di chuyển chuột vào và ra
graph.on('node:mouseenter', (evt) => { const { item } = evt graph.setItemState(item, 'active', true) // hoạt động và được chọn đều là kiểu trạng thái nút}) graph.on( 'node:mouseleave', (evt) => { const { item } = evt graph.setItemState(item, 'active', false) })
12. Tùy chỉnh các kiểu cạnh khác nhau theo các thuộc tính khác nhau của dữ liệu được trả về.
Phần giới thiệu về các nút gần như đã kết thúc. Về kết nối, có ít nội dung hơn về việc xác định động các kiểu kết nối và kiểu văn bản trên các kết nối.
Bạn có thể tùy chỉnh màu kết nối và màu nhãn theo các thuộc tính khác nhau của liên kết. Vì đây là dữ liệu thử nghiệm nên số tự tăng được sử dụng để đánh giá mức độ chẵn lẻ để phân biệt, để hiểu phương pháp tùy chỉnh.
let selfGrowthNum = 0 graph.edge((edge)=> { // let {source, target } = edge // Biểu đồ cạnh của đối tượng selfGrowthNum++ return { style: { opacity: 0.5, stroke: selfGrowthNum % 2 ? '#ADD8E6' : "#FFDEAD", lineWidth: 2 }, labelCfg: { position: 'end', style: { fontSize: 16, fill: selfGrowthNum % 2 ? '#ADD8E6' : "#FFDEAD", } }, label: selfGrowthNum % 2 ? 'even' : "odd" } })
13. Đặt kiểu sao chép mối quan hệ trên đường kết nối
Đoạn mã trên về cơ bản đã hoàn thiện kiểu kết nối và kiểu copywriting, nhưng lúc này, dòng chạy qua văn bản, trông lộn xộn nên kiểu kết nối defaultEdge cần được sửa đổi.
graph = new G6.TreeGraph({ container, width: document.documentElement.clientWidth, Height:document.documentElement.clientHeight, //..... defaultEdge: { type: 'cubic-horizontal', style: { // if Nếu không tùy chỉnh, đây là kiểu mặc định opacity: 0,5, đột quỵ: '#ccc', lineWidth: 2 }, labelCfg: { location: 'end', // Nơi văn bản được hiển thị trong đoạn dòng, refX: -15, style: { fontSize: 16, nền: { fill: '#ffffff', // Thêm màu nền vào văn bản để giải quyết vấn đề vấn đề văn bản bị gạch chéo Phần đệm câu hỏi: [2, 2, 2, 2] } } } } })
14. Giải quyết vấn đề dư ảnh đen khi kéo canvas
Công cụ kết xuất @antv/g@4.x mà G6 4.x dựa vào hỗ trợ kết xuất cục bộ, điều này không chỉ cải thiện hiệu suất mà còn gây ra vấn đề hiển thị dư ảnh khi đồ họa được cập nhật. Ví dụ: khi bạn kéo một nút, văn bản của nút đó sẽ để lại dấu vết. Vì @antv/g hiện đang được nâng cấp phiên bản chính (lên 5.x), nên nó có thể không được coi là khắc phục hoàn toàn sự cố này trong 4.x. Khi gặp phải sự cố này, chúng tôi có thể giải quyết bằng cách tắt hiển thị cục bộ nhưng điều này có thể làm giảm hiệu suất.
graph.get('canvas').set('localRefresh', false)。
15. Trình diễn hoạt hình demo
16. Hoàn thành trường hợp Demo
Cuối cùng, bài viết này về trực quan hóa - Cây nhỏ gọn AntVG6 triển khai các kiểu động của các nút và cạnh, hiển thị nhiều hơn Để biết thông tin về các chức năng nhỏ thực tế như kiểu động, hiển thị nhiều hơn .
Tôi là một lập trình viên xuất sắc, rất giỏi!