热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

設想一個基於svg的塗鴉組件(一)

基於svg寫了一個塗鴉組件,說項目之前先附上幾張結果圖:項目地點:SVGraffiti由於篇幅題目,本文先整體引見一下項目的也許狀況,重點引見一下組件間的通訊體式格局。一、項目申明

基於svg寫了一個塗鴉組件,說項目之前先附上幾張結果圖:

項目地點:SVGraffiti

《設想一個基於svg的塗鴉組件(一)》

《設想一個基於svg的塗鴉組件(一)》

《設想一個基於svg的塗鴉組件(一)》

由於篇幅題目,本文先整體引見一下項目的也許狀況,重點引見一下組件間的通訊體式格局。

一、項目申明
《設想一個基於svg的塗鴉組件(一)》

該項目是基於webpack@3.x.x構建的多頁運用,運用ES6開闢,以組件的體式格局組織代碼。
git clone項目后(文末附上該項目github堆棧地點),npm i裝置相干依靠,npm run dev運轉項目,默許會翻開運用的首頁,也就是上面的結果預覽對應的界面。開闢歷程會單獨地為一些功用編寫一些測試代碼,所以該項目供應了差別的頁面對應於差別的功用,比方:

color picker組件測試頁:
《設想一個基於svg的塗鴉組件(一)》

組件音訊通訊框架測試頁:
《設想一個基於svg的塗鴉組件(一)》

svg底層繪製api測試頁:
《設想一個基於svg的塗鴉組件(一)》

二、組件間通訊
《設想一個基於svg的塗鴉組件(一)》

1、組件間為了完成最大水平的封裝與解耦,不直接舉行相互通訊,而是經由過程“音訊定閱/宣布治理中心”(以下簡稱“音訊中心”)舉行間接通訊。組件經由過程聲明本身為差別的角色從而具有對應的通訊才能:

  • 組件聲明為定閱者(Subscriber)並經由過程@Topics註解的情勢從“音訊中心”定閱本身感興趣的主題音訊,對應的音訊會經由過程notify接口示知組件;
  • 組件聲明為宣布者(Publisher),能夠經由過程Publisher角色注入的publish要領宣布主題音訊;
  • 組件聲明為宣布/定閱者(SubScatterer),同時具有定閱者和宣布者的通訊才能。

這裏以項目中的中心地區的畫板組件為例,由於畫板組件只是吸收Toolbar組件發來的切換繪製才能、清空繪製內容以及Settings組件發來的設置繪製參數信息,所以該組件只是一個音訊定閱者角色,編碼設想以下:

起首導入對應的角色類:

import Subscriber from '../../supports/pubsub/base/subscriber';
import Topics from '../../supports/pubsub/base/topics';

編寫對應的組件:

// 經由過程@Topics的情勢定閱感興趣的音訊範例
@Topics(['function', 'resident_function', 'set_preference'])
export default class Sketchpad extends Subscriber {
// 組織器
constructor(sketchpad) {
super();
this.sketchpad = sketchpad;
// ...
} /**
* 該接口由【PubSub音訊治理中心】擔任挪用,畫板組件在此接口處置懲罰吸收到的音訊範例
* 1、處置懲罰Toolbar組件發送的 “切換畫板繪製狀況” ,對應的音訊範例為:“function”
* 2、處置懲罰Toolbar組件發送的 “清空繪製內容” ,對應的音訊範例為:“resident_function”
* 3、處置懲罰Settings組件發送的 “設置畫板繪製參數” ,對應的音訊範例為:“set_preference”
* @param {String} topic 音訊主題標識
* @param {Object} entity 音訊實體對象
*/
notify(topic, entity) {
// 在此處置懲罰吸收到的音訊
}
}

注:@Topics是靜態的,若有些主題是須要運轉時定閱也能夠挪用Subscriber角色供應的subscribe要領動態定閱音訊。

2、PubSub(音訊定閱/宣布治理中心)的完成
既然是底層通用才能就一定要完成的不帶任何詳細的營業,無論是在定名範例照樣編碼完成上都要保證它是一個通用模塊

PubSub的完成:

/**
* 主題定閱宣布中心
*/
export default class PubSub {
// 緩存主題和主題的定閱者列表
static topics = {};
/**
* 宣布主題音訊
* @param {String} topic 主題
* @param {*} entity 音訊體
*/
static publish(topic, entity) {
if (!PubSub.topics[topic]) return;
// 獵取該主題的定閱者列表
const subscribers = PubSub.topics[topic];
// 向一切該主題的定閱者發送主題音訊
for (let subscriber of subscribers) {
subscriber.notify && subscriber.notify(topic, entity);
}
}
/**
* 一次登記一個主題
* @param {String} topic
*/
static registerTopic(topic) {
const topics = PubSub['topics'];
!topics[topic] && (topics[topic] = []);
}
/**
* 同時登記多個主題
* @param {Array} topics
*/
static registerTopics(topics = []) {
topics.forEach(topic => {
this.registerTopic(topic);
});
}
/**
* 增加主題定閱者
* @param {String} topic 主題
* @param {Object} subscriber 完成了notify接口的定閱者
*/
static addSubscriber(topic, subscriber) {
const topics = PubSub['topics'];
!topics[topic] && (topics[topic] = []);
// 將該主題的定閱者登記到對應的主題
topics[topic].push(subscriber);
} /**
* 刪除對應的定閱者
* @param subscriber
*/
static removeSubscriber(subscriber) {
const subs = [];
// 遍歷一切主題下的定閱者列表,將對應定閱者刪除
const topics = PubSub.topics;
Object.keys(topics).forEach(topicName => {
const topic = topics[topicName];
for (let i = 0; i if (topic[i] === subscriber) {
subs.push(topics[topic].splice(i, 1));
break;
}
}
});
return subs;
}
}

Subscriber的完成:

import PubSub from '../pubsub';
const addSubscribe = (topics = [], context) => {
topics.forEach(topic => {
PubSub.addSubscriber(topic, context);
});
}
/**
* 主題定閱者
*/
export default class Subscriber {
constructor() {
addSubscribe(this.__proto__.constructor.topics, this);
}
subscribe(topic) {
PubSub.addSubscriber(topic, this);
}
}

為了輕易定閱主題,再供應一個@Topics註解:

import PubSub from '../pubsub';
/**
* 定閱者主題裝潢器
* @param {Array} topics
*/
export default function Topics(topics) {
return target => {
target.topics = topics;
PubSub.registerTopics(topics);
}
}

Publisher的完成:

import PubSub from '../pubsub';
/**
* 主題音訊宣布者
*/
export default class Publisher {
publish(topic, entity) {
PubSub.publish(topic, entity);
}
}

SubScatterer的完成:

import PubSub from '../pubsub';
import Subscriber from './subscriber';
/**
* 主題定閱者 and 主題音訊宣布者
*/
export default class SubScatterer extends Subscriber {
publish(topic, entity) {
PubSub.publish(topic, entity);
}
}

本篇引見了項目的也許狀況,重點剖析了怎樣故宣布/定閱的情勢完成組件間的通訊,接下來還會抽時間寫幾個篇離別引見“svg底層繪製才能的封裝”、“畫板差別繪製狀況的完成與治理”、“怎樣開闢一個通用的ColorPicker”等等與本項目相干的文章,寫得不好求親噴。

項目github地點:SVGraffiti

感興趣的同學們迎接star一同交換。


推荐阅读
  • 深入解析:React与Webpack配置进阶指南(第二部分)
    在本篇进阶指南的第二部分中,我们将继续探讨 React 与 Webpack 的高级配置技巧。通过实际案例,我们将展示如何使用 React 和 Webpack 构建一个简单的 Todo 应用程序,具体包括 `TodoApp.js` 文件中的代码实现,如导入 React 和自定义组件 `TodoList`。此外,我们还将深入讲解 Webpack 配置文件的优化方法,以提升开发效率和应用性能。 ... [详细]
  • 本文详细介绍了在 Vue.js 前端框架中集成 vue-i18n 插件以实现多语言支持的方法。通过具体的配置步骤和示例代码,帮助开发者快速掌握如何在项目中实现国际化功能,提升用户体验。同时,文章还探讨了常见的多语言切换问题及解决方案,为开发人员提供了实用的参考。 ... [详细]
  • 更新vuex的数据为什么用mutation?
    更新vuex的数据为什么用mutation?,Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 深入浅出 webpack 系列(二):实现 PostCSS 代码的编译与优化
    在前一篇文章中,我们探讨了如何通过基础配置使 Webpack 完成 ES6 代码的编译。本文将深入讲解如何利用 Webpack 实现 PostCSS 代码的编译与优化,包括配置相关插件和加载器,以提升开发效率和代码质量。我们将详细介绍每个步骤,并提供实用示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 在 Vue 应用开发中,页面状态管理和跨页面数据传递是常见需求。本文将详细介绍 Vue Router 提供的两种有效方式,帮助开发者高效地实现页面间的数据交互与状态同步,同时分享一些最佳实践和注意事项。 ... [详细]
  • 使用 Vuex 管理表单状态:当输入框失去焦点时自动恢复初始值 ... [详细]
  • 在PHP的设计中,预定义了9个超级全局变量、8个魔术变量和13个魔术函数,这些变量和函数无需声明即可在脚本的任意位置使用。这些特性在PHP开发中极为常见,能够显著提升开发效率和代码的灵活性。相比之下,Java并没有类似的内置机制,但通过其他方式如上下文对象和反射机制,也可以实现类似的功能。本文将详细探讨这两种语言中这些特殊变量和函数的使用方法及其应用场景。 ... [详细]
  • 如何在 Node.js 环境中将 CSV 数据转换为标准的 JSON 文件格式? ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • Vue应用预渲染技术详解与实践 ... [详细]
  • 本文探讨了如何通过检测浏览器类型来动态加载特定的npm包,从而优化前端性能。具体而言,仅在用户使用Edge浏览器时加载相关包,以提升页面加载速度和整体用户体验。此外,文章还介绍了实现这一目标的技术细节和最佳实践,包括使用User-Agent字符串进行浏览器识别、条件加载策略以及性能监控方法。 ... [详细]
  • CentOS 7环境下Jenkins的安装与前后端应用部署详解
    CentOS 7环境下Jenkins的安装与前后端应用部署详解 ... [详细]
  • 深入探索Node.js新框架:Nest.js第六篇
    在本文中,我们将深入探讨Node.js的新框架Nest.js,并通过一个完整的示例来展示其强大功能。我们将使用多个装饰器创建一个基本控制器,该控制器提供了多种方法来访问和操作内部数据,涵盖了常见的CRUD操作。此外,我们还将详细介绍Nest.js的核心概念和最佳实践,帮助读者更好地理解和应用这一现代框架。 ... [详细]
  • Node.js 教程第五讲:深入解析 EventEmitter(事件监听与发射机制)
    本文将深入探讨 Node.js 中的 EventEmitter 模块,详细介绍其在事件监听与发射机制中的应用。内容涵盖事件驱动的基本概念、如何在 Node.js 中注册和触发自定义事件,以及 EventEmitter 的核心 API 和使用方法。通过本教程,读者将能够全面理解并熟练运用 EventEmitter 进行高效的事件处理。 ... [详细]
author-avatar
琼小海
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有