热门标签 | 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一同交換。


推荐阅读
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了作者在开发过程中遇到的问题,即播放框架内容安全策略设置不起作用的错误。作者通过使用编译时依赖注入的方式解决了这个问题,并分享了解决方案。文章详细描述了问题的出现情况、错误输出内容以及解决方案的具体步骤。如果你也遇到了类似的问题,本文可能对你有一定的参考价值。 ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
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社区 版权所有