1 Star 0 Fork 2

lzhengms / zhangti0708.github.io

forked from shiyl / zhangti0708.github.io 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
content.json 215.87 KB
一键复制 编辑 原始数据 按行查看 历史
啊嘞嘞嘞 提交于 2020-06-29 13:53 . Site updated: 2020-06-29 13:53:32
[{"title":"cesium | 警情分析城市火灾模拟示例","date":"2020-06-18T09:57:00.000Z","path":"2020/06/18/cesium-警情分析城市火灾模拟/","text":"效果火灾 积水 在线地址:点击访问","tags":[{"name":"GIS","slug":"GIS","permalink":"http://yoursite.com/tags/GIS/"}]},{"title":"[cesium]自定义雷达探测传感器效果","date":"2020-05-28T03:41:00.000Z","path":"2020/05/28/cesium-自定义雷达探测传感器效果/","text":"效果简单粗暴直接上效果 相控雷达传感器 球形相控雷达传感器 信息传输 卫星视锥 雷达跟踪 雷达探测 雷达测控 空间网 插件地址:github地址","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"[cesium]新版本czm内置函数更换","date":"2020-05-28T03:22:00.000Z","path":"2020/05/28/cesium-新版本czm内置函数更换/","text":"前言1记录修改shader和cesium版本迭代替换的一些变量函数。 替换czm_phong12341.5x 之前gl_FragColor = czm_phong(normalize(positionToEyeEC), material) 12341.6x 之后gl_FragColor = czm_phong(normalize(positionToEyeEC), material, lightDirectionEC) czm_ellipsoidInverseRadii12345671.5x 之前float ellipsoidSurfaceFunction(czm_ellipsoid ellipsoid, vec3 point){ vec3 scaled = ellipsoid.inverseRadii * point; return dot(scaled, scaled) - 1.0;} 12345671.6x 之后float ellipsoidSurfaceFunction(vec3 point){ vec3 scaled = czm_ellipsoidInverseRadii * point; return dot(scaled, scaled) - 1.0;}","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"[cesium]基于cesium城市效果示例","date":"2020-05-26T10:46:00.000Z","path":"2020/05/26/cesium-基于cesium城市效果/","text":"效果效果1 效果2 材质动态泛光墙 流动粒子线 od线 说明用的城市白膜,更具不同高度定义颜色 动态效果是自定义的材质和扩散扫描的效果 后续准备加入一些three定义图形 在线地址:点击访问","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"threeJs|开源示例和可视化 (1)","date":"2020-05-25T11:42:00.000Z","path":"2020/05/25/threeJs-开源示例和可视化/","text":"前言1234567891011OpenGL大概许多人都有所耳闻,它是最常用的跨平台图形库。WebGL是基于OpenGL设计的面向web的图形标准,提供了一系列JavaScript API,通过这些API进行图形渲染将得以利用图形硬件从而获得较高性能。 而Three.js是通过对WebGL接口的封装与简化而形成的一个易用的图形库。简单点的说法:WebGL可以看成是浏览器给我们提供的接口,在javascript中可以直接用这些API进行3D图形的绘制;而Three.js就是在这些接口上又帮我们封装得更好用一些。 学习官网: https://threejs.org/ 知乎介绍: https://zhuanlan.zhihu.com/p/23272116?utm_source=wechat_session&utm_medium=social&utm_oi=1018420095655288832 入门指南: https://www.ituring.com.cn/book/1272 在线示例: https://threejs.org/examples/ 开源地址github: https://github.com/mrdoob/three.js three相关资料: https://github.com/chenjsh36/ThreeJSForFun 实现RayData智慧城市: https://zhuanlan.zhihu.com/p/66395021?utm_source=wechat_session&utm_medium=social&utm_oi=1018420095655288832 web3D城市交通: https://zhuanlan.zhihu.com/p/55457466 three示例: https://yyhsong.github.io/iThreeJS/ CesiumThree:https://blog.csdn.net/qq_36266612/article/details/88943501 cesium整合Three示例","tags":[{"name":"ThreeJs","slug":"ThreeJs","permalink":"http://yoursite.com/tags/ThreeJs/"}]},{"title":"cesium | 自定义材质泛光面","date":"2020-05-18T07:31:00.000Z","path":"2020/05/18/cesium-自定义材质泛光面/","text":"效果 实现1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889const DEF_OPT = { color: Cesium.Color.BLUE, duration: 3000, count: 2.0, freely: 'vertical', direction: '-'}CV.PolylineTrailLinkMaterialProperty = class { constructor(options) { options = options || DEF_OPT this._definitionChanged = new Cesium.Event(); this._color = undefined; this._colorSubscription = undefined; this.color = options.color; this.duration = options.duration; this._time = new Date().getTime(); this.create(options) } get isConstant() { return false } get definitionChanged() { return this._definitionChanged } getType(time) { return "PolylineTrailLink"; } getValue (time, result) { if (!Cesium.defined(result)) { result = {}; } result.color = Cesium.Property.getValueOrClonedDefault( this._color, time, Cesium.Color.WHITE, result.color ); result.image = Cesium.Material.PolylineTrailLinkImage; result.time = ((new Date().getTime() - this._time) % this.duration) / this.duration; return result; }; equals(other) { return ( this === other || (other instanceof CV.PolylineTrailLinkMaterialProperty && Cesium.Property.equals(this._color, other._color)) ); } getMaterail(options) { let materail = 【定义的shader材质,csdn博客实现】 } create(options) { Cesium.Material.PolylineTrailLinkType = "PolylineTrailLink"; Cesium.Material.PolylineTrailLinkImage = options.image || "/examples/images/color1.png"; //图片 Cesium.Material.PolylineTrailLinkSource = this.getMaterail(options) Cesium.Material._materialCache.addMaterial( Cesium.Material.PolylineTrailLinkType, { fabric: { type: Cesium.Material.PolylineTrailLinkType, uniforms: { color: new Cesium.Color(1.0, 0.0, 0.0, 0.5), image: Cesium.Material.PolylineTrailLinkImage, time: 0 }, source: Cesium.Material.PolylineTrailLinkSource }, translucent: function (material) { return true; } } ); }}Object.defineProperties(CV.PolylineTrailLinkMaterialProperty.prototype, { color: Cesium.createPropertyDescriptor("color")}); 使用1234entity方式:设置材质material: new CV.PolylineTrailLinkMaterialProperty()","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"随笔| web资料整合","date":"2020-04-30T12:03:00.000Z","path":"2020/04/30/随笔-资料整合/","text":"一. 知识体系: 综合类前端知识体系 前端知识结构 Web前端开发大系概览 Web前端开发大系概览-中文版 Web Front-end Stack v2.2 免费的编程中文书籍索引 前端书籍 前端免费书籍大全 前端知识体系 免费的编程中文书籍索引 智能社 - 精通JavaScript开发 重新介绍 JavaScript(JS 教程) 麻省理工学院公开课:计算机科学及编程导论 JavaScript中的this陷阱的最全收集--没有之一 JS函数式编程指南 JavaScript Promise迷你书(中文版) 腾讯移动Web前端知识库 Front-End-Develop-Guide 前端开发指南 前端开发笔记本 大前端工具集 - 聂微东 前端开发者手册 入门类 前端入门教程 瘳雪峰的Javascript教程 jQuery基础教程 前端工程师必备的PS技能——切图篇 结合个人经历总结的前端入门方法 效果类 弹出层 焦点图轮播特效 工具类 css sprite 雪碧图制作 版本控制入门 – 搬进 Github Grunt-beginner前端自动化工具 慕课专题 张鑫旭 - 慕课系列 lyn - 慕课系列 艾伦 - 慕课系列 碧仔 - Hello,移动WEB 周刊类 百度FEX技术周刊 平安科技移动开发二队技术周报 360奇舞周刊 二. API: 1. 总目录 开发中心 mozilla js参考 chrome开发中心(chrome的内核已转向blink) safari开发中心 microsoft js参考 js秘密花园 js秘密花园 w3help 综合Bug集合网站 综合搜索 javascripting 各种流行库搜索 综合API runoob.com-包含各种API集合 开源中国在线API文档合集 devdocs 英文综合API网站 2. jQuery jQuery API 中文文档 hemin 在线版 css88 jq api css88 jqui api 学习jquery jquery 源码查找 3. Ecmascript Understanding ECMAScript 6 - Nicholas C. Zakas exploring-es6 exploring-es6翻译 exploring-es6翻译后预览 阮一峰 es6 阮一峰 Javascript ECMA-262,第 5 版 es5 4. Js template template-chooser artTemplate tomdjs 淘宝模板juicer模板 Fxtpl v1.0 繁星前端模板引擎 laytpl mozilla - nunjucks Juicer dustjs etpl twitter-tpl 5. 弹出层 artDialog 最新版 artDialog 文档 google code 下载地址 贤心弹出层 响应式用户交互组件库 sweetalert-有css3动画弹出层 6. CSS CSS 语法参考 CSS3动画手册 腾讯css3动画制作工具 志爷css小工具集合 css3 js 移动大杂烩 bouncejs 触摸库 css3 按钮动画 animate.css 全局CSS的终结(狗带) [译] 7. Angularjs Angular.js 的一些学习资源 angularjs中文社区 Angular Style Guide Angularjs源码学习 Angularjs源码学习 angular对bootstrap的封装 angularjs + nodejs 吕大豹 Angularjs AngularJS 最佳实践 Angular的一些扩展指令 Angular数据绑定原理 一些扩展Angular UI组件 Ember和AngularJS的性能测试 带你走近AngularJS - 基本功能介绍 Angularjs开发指南 Angularjs学习 不要带着jQuery的思维去学习AngularJS angularjs 学习笔记 angularjs 开发指南 angularjs 英文资料 angular bootstrap angular jq mobile angular ui 整合jQuery Mobile+AngularJS经验谈 有jQuery背景,该如何用AngularJS编程思想 AngularJS在线教程 angular学习笔记 8. React react海量资源 react.js 中文论坛 react.js 官方网址 react.js 官方文档 react.js material UI react.js TouchstoneJS UI react.js amazeui UI React 入门实例教程 - 阮一峰 React Native 中文版 Webpack 和 React 小书 - 前端乱炖 Webpack 和 React 小书 - gitbook React原创实战视频教程 React 入门教程 react-webpack-starter 基于react组件化开发 9. 移动端API API 99移动端知识集合 移动端前端开发知识库 移动前端的一些坑和解决方法(外观表现) 【原】移动web资源整理 zepto 1.0 中文手册 zepto 1.0 中文手册 zepto 1.1.2 zepto 中文注释 jqmobile 手册 移动浏览器开发集合 移动开发大杂烩 微信webview中的一些问题 框架 特色的HTML框架可以创建精美的iOS应用 淘宝SUI 10. avalon avalonjs Avalon新一代UI库: OniUI avalon.oniui-基于avalon的组件库 11. Requriejs Javascript模块化编程(一):模块的写法 Javascript模块化编程(二):AMD规范 Javascript模块化编程(三):require.js的用法 RequireJS入门(一) RequireJS入门(二) RequireJS进阶(三) requrie源码学习 requrie 入门指南 requrieJS 学习笔记 requriejs 其一 require backbone结合 12. Seajs seajs seajs 中文手册 13. Less,sass sass sass教程-sass中国 Sass 中文文档 less 14. Markdown Markdown 语法说明 (简体中文版) markdown入门参考 gitbook 国外的在线markdown可编辑成书 mdeditor 一款国内的在线markdown编辑器 stackedit 国外的在线markdown编辑器,功能强大,同步云盘 mditor 一款轻量级的markdown编辑器 lepture-editor markdown-editor 15. D3 d3 Tutorials Gallery lofter iteye ruanyifeng 16. 兼容性 esma 兼容列表 W3C CSS验证服务 caniuse csscreator microsoft 在线测兼容-移动端 emulators 17. UI相关 bootcss MetroUICSS semantic Buttons kitecss pintuer amazeui worldhello linuxtoy gitmagic rogerdudler gitref book gogojimmy 18. HTTP HTTP API 设计指南 19. 其它API javascript流行库汇总 验证api underscore 中文手册 underscore源码分析 underscore源码分析-亚里士朱德的博客 underscrejs en api lodash - underscore的代替品 ext4api backbone 中文手册 qwrap手册 缓动函数 svg 中文参考 svg mdn参考 svg 导出 canvas svg 导出 png ai-to-svg localStorage 库 20. 图表类 Highcharts 中文API Highcharts 英文API ECharts 百度的图表软件 高德地图 开源的矢量图脚本框架 svg 地图 21. vue Vue Vue 论坛 Vue 入门指南 Vue 的一些资源索引 21. 正则 JS正则表达式元字符 正则表达式30分钟入门教程 MDN-正则表达式 ruanyifeng - RegExp对象 小胡子哥 - 进阶正则表达式 is.js 正则在线测试 22. ionic ionic 23. 其它 Mock.js 是一款模拟数据生成器 三. 开发规范 前端 通过分析github代码库总结出来的工程师代码书写习惯 HTML&CSS编码规范 by @mdo 团队合作的css命名规范-腾讯AlloyTeam前端团队 前端编码规范之js - by yuwenhui 前端编码规范之js - by 李靖 前端开发规范手册 Airbnb JavaScript 编码规范(简体中文版) AMD与CMD规范的区别 AMD与CMD规范的区别 KISSY 源码规范 bt编码规范 规范加强版 前端代码规范 及 最佳实践 百度前端规范 百度前端规范 百度前端规范 ECMAScript6 编码规范--广发证券前端团队 JavaScript 风格指南/编码规范(Airbnb公司版) 网易前端开发规范 css模块 前端规范资源列表 Nodejs Node.js 风格指南 PHP 最流行的PHP 代码规范 最流行的PHP 代码规范 Android 【敏捷开发】Android团队开发规范 Android 开发规范与应用 四. 其它收集 1. 各大公司开源项目 Facebook Projects 百度web前端研发部 百度EFE 百度github alloyteam alloyteam-github alloyteam-AlloyGameEngine AlloyDesigner 即时修改,即时保存,设计稿较正,其它开发辅助工具 H5交互页编辑器AEditor介绍 H5动画交互页开发的工具介绍 AEditor H5动画交互页开发的工具 maka 值得订阅的weekly 腾讯html5 奇舞团开源项目 Qunar UED 2. Javascript 常用 ieBetter.js-让IE6-IE8拥有IE9+,Chrome等浏览器特性 模拟键盘 拼音 中国个人身份证号验证 算法 数据结构与算法 JavaScript 描述. 章节练习 常见排序算法(JS版) 经典排序 常见排序算法-js版本 JavaScript 算法与数据结构 精华集 面试常考算法题精讲 移动端 fastclick no-click-delay JSON 模拟生成JSON数据 返回跨域JSONAPI 3. Html5 HTML5 有哪些让你惊艳的 demo? html5 Canvas画图系列教程目录 4. CSS browserhacks 5. jQuery 焦点图 myfocus myfocus-官方演示站 SuperSlidev2.1 -- 大话主席 soChange 6. Ext, EasyUI, J-UI 及其它各种UI方案 Ext extjs ext4英文api ext4中文api EasyUI jquery easyui 未压缩源代码 J-UI J-UI Other MUI-最接近原生APP体验的高性能前端框架 Amaze UI | 中国首个开源 HTML5 跨屏前端框架 淘宝 HTML5 前端框架 KISSY - 阿里前端JavaScript库 网易Nej - Nice Easy Javascript Kendo UI MVVM Demo Bootstrap Smart UI 雅虎UI - CSS UI 7. 页面 社会化 分享功能 百度分享 pc端 JiaThis pc端 社会化分享组件 移动端 ShareSDK 轻松实现社会化功能 移动端 友盟分享 移动端 8. 富文本编辑器 百度 ueditor 经典的ckeditor 经典的kindeditor wysiwyg 一个有情怀的编辑器。Bach's Editor tower用的编辑器 summernote 编辑器 html5编辑器 XEditor wangEditor Trumbowyg - 轻量编辑器 9. 日历 PC 经典my97 强大的独立日期选择器 fullcalendar fullcalendar日历控件知识点集合 中文api 农历日历 超酷的仿百度带节日日历老黄历控件 日期格式化 大牛日历控件 我群某管理作品 input按位替换-官网 input按位替换-github bootstrap-daterangepicker 国外30个插件集合 JavaScript datepicker Datepair.js 一个风格多样的日历 弹出层式的全日历 jquery双日历 移动 大气实用jQuery手机移动端日历日期选择插件 jQuery Mobile 移动开发中的日期插件Mobiscroll Date library Datejs sugarjs 10. 综合效果搜索平台 效果网 17素材 常用的JavaScript代码片段 11. 前端工程化 概述 前端工具大全 什么是前端工程化 Gulp Gulp官网 Gulp中文网 gulp资料收集 Gulp:任务自动管理工具 - ruanyifeng Gulp插件 Gulp不完全入门教程 为什么使用gulp? Gulp安装及配合组件构建前端开发一体化 Gulp 入门指南 Gulp 入门指南 - nimojs Gulp入门教程 Gulp in Action Gulp开发教程(翻译) 前端构建工具gulpjs的使用介绍及技巧 Grunt gruntjs Grunt中文网 Fis fis 官网 fis webpack webpack Webpack,101入门体验 webpack入门教程 基于webpack搭建前端工程解决方案探索 Webpack傻瓜式指南(一) Webpack指南 12. 轮播图 pc图轮 单屏轮播sochange 左右按钮多图切换 fullpage全屏轮播 移动端 无缝切换 滑屏效果 全屏fullpage 单个图片切换 单个全屏切换 百度的切换库 单个全屏切换 滑屏效果 旋转拖动设置 类似于swipe切换 支持多种形式的触摸滑动 滑屏效果 大话主席pc移动图片轮换 滑屏效果 基于zepto的fullpage [WebApp]定宽网页设计下,固定宽度布局开发WebApp并实现多终端下WebApp布局自适应 判断微信客户端的那些坑 可以通过javascript直接调用原生分享的工具 JiaThis 分享到微信代码 聊聊移动端跨平台开发的各种技术 前端自动化测试 多种轮换图片 滑动侧边栏 13. 文件上传 百度上传组件 上传 flash 头像上传 图片上传预览 图片裁剪 图片裁剪-shearphoto jQuery图片处理 14. 模拟select 糖饼 select flexselect 双select select2 15. 取色插件 类似 Photoshop 的界面取色插件 jquery color 取色插件集合 farbtastic 圆环+正方形 16. 城市联动 jquery.cityselect.js基于jQuery+JSON的省市或自定义联动效果 17. 剪贴板 剪贴板 clipboard 最新的剪切方案 18. 简繁转换 简繁转换 19. 表格 Grid facebook表格 类似于Excel编辑表格-handsontable bootstrap-table插件 datatables 20. 在线演示 js 在线编辑 - runjs js 在线编辑 - jsbin js 在线编辑 - codepen js 在线编辑 - jsfiddle java 在线编辑 - ideone js 在线编辑 - hcharts js 在线编辑 - jsdm sql 在线编辑 - sqlfiddle mozilla 在线编辑器 21. 播放器 Html5 VideoPlayer 22. 粒子动画 Proton 烟花 23. 表单验证 Validform formvalidator jQuery formValidator 五. Nodejs nodejs 篇幅比较巨大 Node.js 包教不包会 篇幅比较少 node express 入门教程 nodejs定时任务 一个nodejs博客 【NodeJS 学习笔记04】新闻发布系统 过年7天乐,学nodejs 也快乐 七天学会NodeJS Nodejs学习笔记(二)--- 事件模块 nodejs入门 angularjs nodejs 从零开始nodejs系列文章 理解nodejs nodejs事件轮询 node入门 nodejs cms Node初学者入门,一本全面的NodeJS教程 NodeJS的代码调试和性能调优 六. 性能优化 常规优化 Javascript高性能动画与页面渲染 移动H5前端性能优化指南 5173首页前端性能优化实践 给网页设计师和前端开发者看的前端性能优化 复杂应用的 CSS 性能分析和优化建议 张鑫旭——前端性能 前端性能监控总结 网站性能优化之CSS无图片技术 web前端性能优化进阶路 前端技术:网站性能优化之CSS无图片技术 浏览器的加载与页面性能优化 页面加载中的图片性能优化 Hey——前端性能 html优化 99css——性能 Yslow——性能优化 YSLOW中文介绍 转一篇Yahoo关于网站性能优化的文章,兼谈本站要做的优化 Yahoo!团队实践分享:网站性能 网站性能优化指南:什么使我们的网站变慢? 网站性能优化实践,减少加载时间,提高用户体验 浅谈网站性能优化 前端篇 前端重构实践之如何对网站性能优化? 前端性能优化:使用媒体查询加载指定大小的背景图片 网站性能系列博文 加载,不只是少一点点 前端性能的测试与优化 分享网页加载速度优化的一些技巧? 页面加载中的图片性能优化 web前端优化(基于Yslow) 网站性能优化工具大全 【高性能前端1】高性能HTML 【高性能前端2】高性能CSS 由12306谈谈网站前端性能和后端性能优化 AlloyTeam——前端优化 毫秒必争,前端网页性能最佳实践 网站性能工具Yslow的使用方法 前端工程与性能优化(上):静态资源版本更新与缓存 前端工程与性能优化(下):静态资源管理与模板框架 HTTPS连接的前几毫秒发生了什么 Yslow Essential Web Performance Metrics — A Primer, Part 1 Essential Web Performance Metrics — Part 2 YUISlide,针对移动设备的动画性能优化 Improving Site Performance 让网站提速的最佳前端实践 Why Website Speed is Important Need for Speed – How to Improve your Website Performance 阿里无线前端性能优化指南 (Pt.1 加载期优化) 优化工具 JavaScript 性能分析新工具 OneProfile JavaScript 堆内存分析新工具 OneHeap 在线工具 google在线工具 阿里测 阿里-免费测试服务 阿里-F2etest多浏览器兼容性测试解决方案 js性能测试 轻松玩转PDF 七. 前端架构 技术架构 前端架构 如何成为前端架构师 关于前端架构-张克军 百度腾讯offer比较(腾讯游戏VS百度基础架构)   八. iconfont 中文字体 淘宝字库 字体 制作教程 zhangxinxu-icommon icommon 用字体在网页中画ICON图标(推荐教程) 字体压缩工具 感谢初级群 [深圳-小鱼] 的推荐 九. 开发工具类 前端开发工具 IntelliJ IDEA 简体中文专题教程 Webstorm,InterllIdea,Phpstorm SublimeText Atom visual studio code Chrome, Firebug, Filddle 调试 Fiddler Fiddler调式使用知多少(一)深入研究 微信fiddle 微信fiddle Chrome Google Chrome 官方 Chrome - 基础 Chrome - 进阶 Chrome - 性能 Chrome - 性能进阶 Chrome - 移动 Chrome - 使用技巧 Chrome - Console控制台不完全指南 Chrome - Workspace使浏览器变成IDE network面板 chrome开发工具快捷键 chrome调试工具常用功能整理 Chrome 开发工具 Workspace 使用 Chrome神器Vimium快捷键学习记录 sass调试-w3cplus 如何更专业的使用Chrome开发者工具-w3cplus chrome调试canvas chrome profiles1 chrome profiles2 chrome profiles3 chrome移动版调试 chrome调试 chrome的调试 chrome console 命令详解 查看事件绑定1 查看事件绑定2 神器——Chrome开发者工具(一) 奇趣百科性能优化(Chrome DevTools 中的 Timeline Profils 等工具使用介绍) chrome 开发者工具的 15 个小技巧 Chrome开发者工具不完全指南 Chrome 开发者工具使用技巧 Firebug firebug视频教程 firefox 模拟器 console.log 命令详解 Firebug入门指南 Firebug控制台详解 移动,微信调试 微信调试的那些事 微信调试官网 微信公众号本地调试 微信、手Q、Qzone之x5内核inspect调试解决方案 浏览器端调试安卓 移动端前端开发调试 使用 Chrome 远程调试 Android 设备 mac移动端调试 mac移动端调试 无线调试攻略 无线调试攻略 屌爆了,完美调试 微信webview(x5) 远程console 微信调试工具 各种真机远程调试方法汇总 手机测试自己写的web页面 iOS Simulator Simulator Xcode中的iOS模拟器(iOS Simulator)的介绍和使用心得 img loading img 智图-图片优化平台 在线png优化 生成二维码 生成二维码 浏览器同步 puer liveReload f5 File Watchers 在线PPT制作 nodePPT PPT reveal slippy 十. 前端导航网站 界面清爽的前端导航 前端导航 前端网址导航 前端名录 前端导航 前端开发资源 网址导航 前端开发仓库 - 众多效果的收集地 前端资源导航 F2E 前端导航 前端收藏夹 pFan 前端开发导航平台 十一. 常用CDN 新浪CDN 百度静态资源公共库 360网站卫士常用前端公共库CDN服务 Bootstrap中文网开源项目免费 CDN 服务 开放静态文件 CDN - 七牛 CDN加速 - jq22 jQuery CDN Google jQuery CDN 微软CDN 十二. Git,SVN,Github Git git-scm 廖雪峰-Git教程 git-for-windows GitHub 添加 SSH keys gogithub git常规命令练习 git的资料整理 我所记录的git命令(非常实用) 企业开发git工作流模式探索部分休整 GitHub 漫游指南 GitHub秘籍 使用git和github进行协同开发流程 动画方式练习git 版本管理工具介绍—Git篇 版本控制入门 – 搬进 Github Git动画演示 SVN 版本管理工具介绍---SVN篇","tags":[{"name":"web","slug":"web","permalink":"http://yoursite.com/tags/web/"}]},{"title":"Vue|基于Vue的webGIS展示","date":"2020-04-27T05:27:00.000Z","path":"2020/04/27/Vue-基于Vue的webGIS展示/","text":"前言对之前那版的三维gis示例修改重构,使用vue+elementui集成。展示一些基础功能和拓展功能,部分拓展功能为开放。对每个示例加入一些基本操作,模型查看,场景调整等。 效果图1. 地图 2. 控件 数据 3. 三维效果 功能 4. 空间分析 数据可视化 5. 示例示例1 示例2 示例3 示例4 示例5 示例6 示例7 示例8 示例9 示例10 以前的版本:传送门","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"webGL|webgl2.0工作原理[转]","date":"2020-04-27T04:36:00.000Z","path":"2020/04/27/webGL-webgl2-0工作原理-转/","text":"WebGL2 工作原理看了这个文章会让你更知道怎么写 WebGL 代码而已。 原理细节远远不够, 更多的细节应该是看Opengl ,图形渲染管线, CPU与GPU通信, GPU流水线 。 WebGL 工作原理我们需要探讨一下WebGL在GPU上究竟做了什么。WebGL在GPU上的工作基本上分为两部分,第一部分是将顶点(或数据流)转换到裁剪空间坐标, 第二部分是基于第一部分的结果绘制像素点。 当你调用 gl.drawArrays(gl.TRIANGLE, 0, 9);这里的9表示“处理9个顶点”,所以将会有9个顶点被转换。 左侧是你提供的数据。顶点着色器(Vertex Shader)是你写进GLSL 中的一个方法,每个顶点调用一次,在这个方法中做一些数学运算后设置了一个特殊的gl_Position变量, 这个变量就是该顶点转换到裁剪空间中的坐标值,GPU接收该值并将其保存起来。 假设你正在画三角形,顶点着色器每完成三次顶点处理,WebGL就会用这三个顶点画一个三角形。它计算出这三个顶点对应的像素后,就会光栅化这个三角形,“光栅化”其实就是“用像素画出来” 的花哨叫法。对于每一个像素,它会调用你的片断着色器询问你使用什么颜色。你通过给片断着色器的一个特殊变量gl_FragColor设置一个颜色值,实现自定义像素颜色。 使用它们可以做出非常有趣的东西,但如你所见,到目前为止的例子中, 处理每个像素时片断着色器可用信息很少,幸运的是我们可以给它传递更多信息。想要从顶点着色器传值到片断着色器,我们可以定义“可变量(varyings)”。 一个简单的例子,将顶点着色器计算出的裁剪空间坐标从顶点着色器传递到片断着色器。 我们来画一个简单的三角形。 12345678910// 定义一个三角形填充到缓冲里function setGeometry(gl) {gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([0, -100,150, 125,-175, 100]),gl.STATIC_DRAW);} 我们只需要画三个顶点。 123456// Draw the scene.function drawScene() {...// Draw the geometry.gl.drawArrays(gl.TRIANGLES, 0, 3);} 然后在我们的顶点着色器中定义一个varying(可变量)用来给片断着色器传值。 1234567891011varying vec4 v_color;...void main() {// 将位置和矩阵相乘gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1); // 从裁减空间转换到颜色空间// 裁减空间范围 -1.0 到 +1.0// 颜色空间范围 0.0 到 1.0v_color = gl_Position * 0.5 + 0.5;} 在片断着色器中定义同名varying变量。 12345678#version 300 esprecision mediump float;in vec4 v_color;out vec4 outColor; void main() {outColor = v_color;} WebGL会将同名的可变量从顶点着色器输入到片断着色器中。 下面是运行结果。 点此在新窗口中浏览 当你移动,缩放,旋转三角形时,发现颜色随位置变化,不跟着三角形移动。 回想一下,我们只计算了三个顶点,调用了三次顶点着色器,所以也只计算出了三个颜色值, 但是我们的三角形却有很多颜色,这就是称之为可变量的varying的原因啦! WebGL先获得顶点着色器中计算的三个颜色值,在光栅化三角形时将会根据这三个值进行插值。每一个像素在调用片断着色器时,可变量的值是与之对应的插值。 让我们从上例的三个顶点开始分析 顶点0-100150125-175100 我们的给顶点着色器施加了一个包含平移,旋转和缩放的的矩阵,并将结果转换到裁剪空间。默认平移,旋转和缩放值为:平移 = 200, 150,旋转 = 0,缩放 = 1,所以这里只进行了平移。画布大小(背景缓冲)为 400×300,所以三个顶点在裁剪空间中为以下坐标值。 写入 gl_Position 的值0.0000.6600.750-0.830-0.875-0.660 同时将这些值转换到颜色空间中赋给我们定义的可变量v_color。 写入 v_color 的值0.50000.8300.50.87500.0860.50.06250.1700.5 利用这三个值进行插值后传进每个像素运行的片断着色器中。 v_color在v0,v1和v2之间插值 想要给片断着色器传值,我们可以先把值传递给顶点着色器然后再传给片断着色器。让我们来画一个由两个不同颜色三角形组成的矩形。我们需要给顶点着色器添加一个属性值, 把值通过属性传递给它后它再直接传递给片断着色器。 12345678910attribute vec2 a_position;attribute vec4 a_color;...varying vec4 v_color; void main() {...// 直接把属性值中的数据赋给可变量v_color = a_color;} 现在要给WebGL提供要用的颜色. 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647// look up where the vertex data needs to go.var positionLocation = gl.getAttribLocation(program, "a_position");var colorLocation = gl.getAttribLocation(program, "a_color");...// Create a buffer for the colors.var buffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // Set the colors.setColors(gl); // setup attributes...// tell the color attribute how to pull data out of the current ARRAY_BUFFERgl.enableVertexAttribArray(colorLocation);var size = 4;var type = gl.FLOAT;var normalize = false;var stride = 0;var offset = 0;gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset); ... // Fill the buffer with colors for the 2 triangles// that make the rectangle.function setColors(gl) {// Pick 2 random colors.var r1 = Math.random();var b1 = Math.random();var g1 = Math.random(); var r2 = Math.random();var b2 = Math.random();var g2 = Math.random(); gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([ r1, b1, g1, 1,r1, b1, g1, 1,r1, b1, g1, 1,r2, b2, g2, 1,r2, b2, g2, 1,r2, b2, g2, 1]),gl.STATIC_DRAW);} 这里是结果。 点此在新窗口中浏览 你可能注意到这两个三角形是纯色的。我们传递给每个三角形的顶点的颜色值是相同的, 所以我们传递的varying会被插值成相同的颜色,如果我们传递不同的颜色,就会看到插值的颜色。 123456789101112131415// 给矩形的两个三角形// 设置颜色值并发到缓冲function setColors(gl) {// 给每个顶点定义不同的颜色gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([ Math.random(), Math.random(), Math.random(), 1,Math.random(), Math.random(), Math.random(), 1,Math.random(), Math.random(), Math.random(), 1,Math.random(), Math.random(), Math.random(), 1,Math.random(), Math.random(), Math.random(), 1,Math.random(), Math.random(), Math.random(), 1]),gl.STATIC_DRAW);} 现在看到的是插值的varying。 点此在新窗口中浏览 可能不值一提的是上例还演示了使用多个属性并且通过顶点着色器向片断着色器传值。如果你看了处理图片的例子, 那里面还用了另外一个属性传递纹理坐标。 关于buffer和attribute的代码是干什么的? 缓冲操作是在GPU上获取顶点和其他顶点数据的一种方式。gl.createBuffer创建一个缓冲;gl.bindBuffer是设置缓冲为当前使用缓冲;gl.bufferData将数据拷贝到缓冲,这个操作一般在初始化完成。 一旦数据存到缓冲中,还需要告诉WebGL怎么从缓冲中提取数据传给顶点着色器的属性。 要做这些,首先需要获取WebGL给属性分配的地址,如下方代码所示 123// 询问顶点数据应该放在哪里var positionLocation = gl.getAttribLocation(program, "a_position");var colorLocation = gl.getAttribLocation(program, "a_color"); 这一步一般也是在初始化部分完成。 一旦知道了属性的地址,在绘制前还需要发出三个命令。 gl.enableVertexAttribArray(location);这个命令是告诉WebGL我们想从缓冲中提供数据。 gl.bindBuffer(gl.ARRAY_BUFFER, someBuffer);这个命令是将缓冲绑定到 ARRAY_BUFFER 绑定点,它是WebGL内部的一个全局变量。 1234567gl.vertexAttribPointer(location,numComponents,typeOfData,normalizeFlag,strideToNextPieceOfData,offsetIntoBuffer); 这个命令告诉WebGL从 ARRAY_BUFFER绑定点当前绑定的缓冲获取数据。每个顶点有几个单位的数据(1 - 4),单位数据类型是什么(BYTE, FLOAT, INT, UNSIGNED_SHORT, 等等…), stride 是从一个数据到下一个数据要跳过多少位,最后是数据在缓冲的什么位置。 单位个数永远是 1 到 4 之间。 如果每个类型的数据都用一个缓冲存储,stride 和 offset 都是 0 。对 stride 来说 0 表示 “用符合单位类型和单位个数的大小”。对 offset 来说 0 表示从缓冲起始位置开始读取。它们使用 0 以外的值时会复杂得多,虽然这样会取得一些性能能上的优势, 但是一般情况下并不值得,除非你想充分压榨WebGL的性能。 希望这些关于缓冲和属性的内容对你来说讲的足够清楚。 vertexAttribPointer 中的 normalizeFlag 参数是什么意思? 标准化标记(normalizeFlag)适用于所有非浮点型数据。如果传递false就解读原数据类型。BYTE 类型的范围是从 -128 到 127,UNSIGNED_BYTE 类型的范围是从 0 到 255, SHORT 类型的范围是从 -32768 到 32767,等等… 如果标准化标记设为true,BYTE 数据的值(-128 to 127)将会转换到 -1.0 到 +1.0 之间, UNSIGNED_BYTE (0 to 255) 变为 0.0 到 +1.0 之间,SHORT 也是转换到 -1.0 到 +1.0 之间, 但比 BYTE 精确度高。 最常用的是标准化颜色数据。大多数情况颜色值范围为 0.0 到 +1.0。使用4个浮点型数据存储红,绿,蓝和阿尔法通道数据时,每个顶点的颜色将会占用16字节空间, 如果你有复杂的几何体将会占用很多内存。代替的做法是将颜色数据转换为四个 UNSIGNED_BYTE , 其中 0 表示 0.0,255 表示 1.0。现在每个顶点只需要四个字节存储颜色值,省了 75% 空间。 我们来修改之前代码实现。当我们告诉WebGL如何获取颜色数据时将这样 123456789101112131415161718192021222324252627282930313233// 告诉颜色属性如何从colorBuffer中提取数据 (ARRAY_BUFFER)var size = 4; // 每次迭代使用四个单位数据var type = gl.UNSIGNED_BYTE; // 数据类型是8位的 UNSIGNED_BYTE 类型。var normalize = true; // 标准化数据var stride = 0; // 0 = 移动距离 * 单位距离长度sizeof(type)// 每次迭代跳多少距离到下一个数据var offset = 0; // 从缓冲的起始处开始gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset)如下向缓冲添加数据// 给矩形的两个三角形// 设置颜色值并发到缓冲function setColors(gl) {// 设置两个随机颜色var r1 = Math.random() * 256; // 0 到 255.99999 之间var b1 = Math.random() * 256; // 这些数据var g1 = Math.random() * 256; // 在存入缓冲时var r2 = Math.random() * 256; // 将被截取成var b2 = Math.random() * 256; // Uint8Array 类型var g2 = Math.random() * 256; gl.bufferData(gl.ARRAY_BUFFER,new Uint8Array( // Uint8Array[ r1, b1, g1, 255,r1, b1, g1, 255,r1, b1, g1, 255,r2, b2, g2, 255,r2, b2, g2, 255,r2, b2, g2, 255]),gl.STATIC_DRAW);} 这里是结果。","tags":[{"name":"WebGL","slug":"WebGL","permalink":"http://yoursite.com/tags/WebGL/"}]},{"title":"cesium|源码跟读 - cesium的数据调度渲染过程","date":"2020-04-25T15:41:00.000Z","path":"2020/04/25/cesium-源码跟读-数据调度/","text":"前言学习源码的时候有一个好的学习方案往往能事半功倍。 在跟读源码时定下一个学习目标,记录学习过程。 比如需要了解那个API的初始化过程来作为学习导向。 这篇已cesium如何渲染地形和影像为学习导向来研究cesium的数据调度机制 数据调度之前讲过cesiumWidget如何初始化的,里边说到场景内的数据会自动做每一帧的循环渲染。 startRenderLoop 开始渲染三维窗口内的对象 通过requestAnimationFrame函数循环渲染,每一帧的结束,就是下一帧的开始 使用requestAnimationFrame创建一个draw循环 每个动画帧都调用tick回调函数 最终都会都用scene.render()函数 其中 地形和影像 都是在globe.beginframe 和 globe.endframe之间完成渲染的 调度说明updateAndExecuteCommands 负责数据的调度,比如哪些Tile需要创建,这些Tile相关的地形数据,以及涉及到的影像数据之间的调度,都是在该函数中维护。但是updateAndExecuteCommands函数只负责管理,也就是他所创建的Tile类只是一个个的Tasks,自己并不负责Tasks内容的实现(数据的加载和维护)。这样,导致架构会有些复杂,因为不是一个流水线的作业方式,所以就需要有状态的维护。但这也是必然的,不仅保证该函数高效,不拖累每一帧的时间消耗,同时因为实时性满足人的要求(帧数能够达到或接近60),每一帧需要的Tile队列可以实时计算,不用考虑时间和状态之间的关系。 可以这样理解,updateAndExecuteCommands是一个管理者,只说不做,与之相反,scene.globe.endFrame中,会对该帧所涉及的GlobeTile的下载,解析等进行处理 简单而言,updateAndExecuteCommands负责上面看得见的事情,根据当前这一帧相机的状态,先打一个黄色的网格,然后检查当前状态下,这些网格里面的地形和影像数据是否都已经准备好了,如果准备好,每一个Tile就创建一个DrawCommand来渲染,把这个球画出来。如果没准备好也不管,反正有endFrame函数负责,各司其职 scene.globe.endFrame就按照吩咐来准备每一个Tile的数据,全是看不见的工作,默默的奉献自己的青春。这里,Promise,Worker等技术都会使用,通过异步和多线程的方式,来缓解每一帧的负担,而在主线程下,主要是数据状态的维护。如果一个Tile的数据解析完成,则该GlobeTile的状态更新为renderable(可渲染),done(已完成)。 类关系图 在这个过程中,类的关系大致如下: 网格按照经纬度来划分的,每一个网格对应一个QuadtreeTile四叉树类,其中有一个GlobeSurfaceTile,里面保存地形数据TileTerrain和影像数据TileImagery。当前相机下需要多个网格,就需要多个QuadtreeTile,该队列保存在QuadtreePrimitive,QuadtreePrimitive统一维护所有Tile的管理,具体是通过GlobeSurfaceTileProvider来实现逻辑操作,而QuadtreePrimitive上面包了一个Globe和Scene 初始化globe 创建QuadtreePrimitive数据队列对象, 该对象会实例化 一个GlobeSurfaceTileProvider将地形和影像数据分别存储进去 渲染过程 地形和影像的渲染是通过updateAndExecuteCommands完成数据调度 关系图 源码跟读 scene.updateAndExecuteCommands 开始执行 scene.executeCommandsInViewport 方法 执行 updateAndRenderPrimitives 调用globe的update函数 globe.update调用数据队列的update 最终调用GlobeSurfaceTileProvider 实现逻辑 渲染说明 在QuadtreePrimitive的update中,调用selectTilesForRendering来或许当前需要创建的网格,其中,在第一帧会把全球分为两块Tile: 而在queueChildrenLoadAndDetermineIfChildrenAreAllRenderable函数中,基于这两个Tile来做四叉树剖分,也就是所有的后来的QuadtreeTile都能够上溯到这两个Tile之一: 创建的GlobeSurfaceTile都会存储到更新队列中,等待数据下载和解析的过程,而如果当前帧中,存在准备好的,已经可以渲染的GlobeSurfaceTile,则调用addDrawCommandsForTile,构造成VBO,最终通过WebGL实现渲染。 更新过程 用大佬的原文解释: 参考博文 : https://www.cnblogs.com/fuckgiser/p/5744509.html","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|源码跟读 - CesiumWidget","date":"2020-04-25T15:05:00.000Z","path":"2020/04/25/cesium-源码跟读-CesiumWidget/","text":"CesiumWidget三维窗口对象 cesium的核心Api 通过实例化CesiumWidget 创建cesium容器和canvas画布 渲染三维场景和管理场景控件等 结构图 初始化流程实例化CesiumWidget 流程 获取cesium页面容器,挂载三维窗口widget对象,创建canvas画布对象初始化信用容器innerCreditContainer挂载到页面 实例化窗口部件,初始化场景和配置场景内的参数。添加场景屏幕事件 设置是否循环渲染,cesium中数据渲染会按批次进行每一帧的渲染 默认渲染,通过requestAnimationFrame函数进行循环渲染场景,每次结束都会调用scene.render() 初始化场景内的组件globe,SkyBox,Sun,Moon 基本属性和方法函数 主要函数render 渲染场景。该功能会自动调用除非 useDefaultRenderLoop 设置为false; resize 更新画布大小,相机纵横比和视口大小。除非需要,否则将自动调用此函数 useDefaultRenderLoop 设置为false。 destroy 销毁小部件。如果被永久调用从布局中删除小部件。 showErrorPanel 向用户显示错误面板,其中包含标题和较长的错误消息,可以使用’确定’按钮将其关闭。该面板自动显示发生渲染循环错误时,如果showRenderLoopErrors不为false,则当小部件已构建 说明官网案例使用的都是Cesium.Viewer这个窗体组件,包含了非常丰富的组件内容。Cesium.CesiumWidget可以说是其简化版本,不包含动画、图层选择等等其他组件内容,仅仅显示一个三维数字地球。并且,默认情况下也不会包含Cesium地形的图层。 创建一个纯净的地球 new Cesium.CesiumWidget('cesiumContainer');","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|视线分析(环视,通视)","date":"2020-04-20T08:28:00.000Z","path":"2020/04/20/cesium-环视分析/","text":"通视分析 检测观察点是否可视,设置起终点创建射线,通过求交函数pickFromRay计算与一段射线相交的碰撞点并返回相交点。最后绘制相交位置点,以此为分析点绘制通视线 环视分析(3dtileset) 通过绘制椭圆计算椭圆边的位置点,通过中心点和边界点计算线段差值。将计算的差值点数组与场景范围内的3dtileset数据,使用clampToHeightMostDetailed查询每个位置点与当前场景内的3dtileset的clipToHeight夹紧位置,通过线段差值计算相邻的两点高度是否递增 部分实现射线求交实现 12345678910111213141516171819202122232425/** * 获取相交对象 * @param {*} startPos * @param {*} endPos * @param {*} excludeArr * @param {*} bDrillPick */ _getIntersectObj(startPos, endPos, excludeArr = [], bDrillPick = false) { var viewer = this._viewer; var direction = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(endPos, startPos, new Cesium.Cartesian3()), new Cesium.Cartesian3()); var ray = new Cesium.Ray(startPos, direction); //无限延长的射线 var results = []; if (bDrillPick) { results = viewer.scene.drillPickFromRay(ray, 10, excludeArr); } else //只pick首个物体 { var result = viewer.scene.pickFromRay(ray, excludeArr); if (Cesium.defined(result)) { results = [result]; } } return results; }","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|挖地形,地形坡度和模拟地形淹没","date":"2020-04-20T06:27:00.000Z","path":"2020/04/20/sium-挖地形和模拟地形淹没/","text":"效果挖地形 通过绘制多边形获取边界点集合,把边界点分别计算生成多个ClippingPlane面 ,用ClippingPlaneCollection接口生成裁剪地形效果。最后分别将侧边和底部加上贴图效果 淹没分析 通过绘制多边形获取边界点集合,用extrudedHeight属性动态控制淹没高度,简单模拟淹没效果。熟悉webgl的可以通过修改shader的顶点和片段着色器创建淹没效果 坡度分析(地形)通过绘制多段线获取线段点集合,用lerp获取点的线性插值结果,将返回的差值点高程绘制出来,实现坡度图 说明挖地形插件 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241import Cesium from '../namespace'function TerrainClipPlan(t, i) { this.viewer = t, this.options = i || {}, this._positions = i.positions, this._height = this.options.height || 0, this.bottomImg = i.bottomImg, this.wallImg = i.wallImg, this.splitNum = Cesium.defaultValue(i.splitNum, 50), this._positions && this._positions.length > 0 && this.updateData(this._positions)}Object.defineProperties(TerrainClipPlan.prototype, { show: { get: function () { return this._show }, set: function (e) { this._show = e, this.viewer.scene.globe.clippingPlanes && (this.viewer.scene.globe.clippingPlanes.enabled = e), this._switchExcavate(e) } }, height: { get: function () { return this._height }, set: function (e) { this._height = e, this._updateExcavateDepth(e) } }})TerrainClipPlan.prototype.updateData = function (e) { this.clear(); var t = [], i = e.length, a = new Cesium.Cartesian3, n = Cesium.Cartesian3.subtract(e[0], e[1], a); n = n.x > 0, this.excavateMinHeight = 9999; for (var r = 0; r < i; ++r) { var s = (r + 1) % i, l = Cesium.Cartesian3.midpoint(e[r], e[s], new Cesium.Cartesian3), u = Cesium.Cartographic.fromCartesian(e[r]), c = this.viewer.scene.globe.getHeight(u) || u.height; c < this.excavateMinHeight && (this.excavateMinHeight = c); var d, h = Cesium.Cartesian3.normalize(l, new Cesium.Cartesian3); d = n ? Cesium.Cartesian3.subtract(e[r], l, new Cesium.Cartesian3) : Cesium.Cartesian3.subtract(e[s], l, new Cesium.Cartesian3), d = Cesium.Cartesian3.normalize(d, d); var f = Cesium.Cartesian3.cross(d, h, new Cesium.Cartesian3); f = Cesium.Cartesian3.normalize(f, f); var p = new Cesium.Plane(f, 0), m = Cesium.Plane.getPointDistance(p, l); t.push(new Cesium.ClippingPlane(f, m)) } this.viewer.scene.globe.clippingPlanes = new Cesium.ClippingPlaneCollection({ planes: t, edgeWidth: 1, edgeColor: Cesium.Color.WHITE, enabled: !0 }), this._prepareWell(e), this._createWell(this.wellData)}TerrainClipPlan.prototype.clear = function () { this.viewer.scene.globe.clippingPlanes && (this.viewer.scene.globe.clippingPlanes.enabled = !1, this.viewer.scene.globe.clippingPlanes.removeAll(), this.viewer.scene.globe.clippingPlanes.isDestroyed() || this.viewer.scene.globe.clippingPlanes.destroy()), this.viewer.scene.globe.clippingPlanes = void 0, this.bottomSurface && this.viewer.scene.primitives.remove(this.bottomSurface), this.wellWall && this.viewer.scene.primitives.remove(this.wellWall), delete this.bottomSurface, delete this.wellWall, this.viewer.scene.render()}TerrainClipPlan.prototype._prepareWell = function (e) { var t = this.splitNum, i = e.length; if (0 != i) { for (var a = this.excavateMinHeight - this.height, n = [], r = [], s = [], l = 0; l < i; l++) { var u = l == i - 1 ? 0 : l + 1, c = Cesium.Cartographic.fromCartesian(e[l]), d = Cesium.Cartographic.fromCartesian(e[u]), h = [c.longitude, c.latitude], f = [d.longitude, d.latitude]; 0 == l && ( s.push(new Cesium.Cartographic(h[0], h[1])), r.push(Cesium.Cartesian3.fromRadians(h[0], h[1], a)), n.push(Cesium.Cartesian3.fromRadians(h[0], h[1], 0))); for (var p = 1; p <= t; p++) { var m = Cesium.Math.lerp(h[0], f[0], p / t), g = Cesium.Math.lerp(h[1], f[1], p / t); l == i - 1 && p == t || ( s.push(new Cesium.Cartographic(m, g)), r.push(Cesium.Cartesian3.fromRadians(m, g, a)), n.push(Cesium.Cartesian3.fromRadians(m, g, 0))) } } this.wellData = { lerp_pos: s, bottom_pos: r, no_height_top: n } }}TerrainClipPlan.prototype._createWell = function (e) { if (Boolean(this.viewer.terrainProvider._layers)) { var t = this; this._createBottomSurface(e.bottom_pos); var i = Cesium.sampleTerrainMostDetailed(this.viewer.terrainProvider, e.lerp_pos); Cesium.when(i, function (i) { for (var a = i.length, n = [], r = 0; r < a; r++) { var s = Cesium.Cartesian3.fromRadians(i[r].longitude, i[r].latitude, i[r].height); n.push(s) } t._createWellWall(e.bottom_pos, n) }) } else { this._createBottomSurface(e.bottom_pos); this._createWellWall(e.bottom_pos, e.no_height_top) }}TerrainClipPlan.prototype._getMinHeight = function (e) { let minHeight = 5000000; let minPoint = null; for (let i = 0; i < e.length; i++) { let height = e[i]['z']; if (height < minHeight) { minHeight = height; minPoint = this._ellipsoidToLonLat(e[i]); } } return minPoint.altitude;}TerrainClipPlan.prototype._ellipsoidToLonLat = function (c) { let ellipsoid = this.viewer.scene.globe.ellipsoid; let cartesian3 = new Cesium.Cartesian3(c.x, c.y, c.z); let cartographic = ellipsoid.cartesianToCartographic(cartesian3); let lat = Cesium.Math.toDegrees(cartographic.latitude); let lng = Cesium.Math.toDegrees(cartographic.longitude); let alt = cartographic.height; return { longitude: lng, latitude: lat, altitude: alt }}TerrainClipPlan.prototype._createBottomSurface = function (e) { if (e.length) { let minHeight = this._getMinHeight(e); let positions = []; for (let i = 0; i < e.length; i++) { let p = this._ellipsoidToLonLat(e[i]); positions.push(p.longitude); positions.push(p.latitude); positions.push(minHeight); } let polygon = new Cesium.PolygonGeometry({ polygonHierarchy: new Cesium.PolygonHierarchy( Cesium.Cartesian3.fromDegreesArrayHeights(positions) ), perPositionHeight: true }); let geometry = Cesium.PolygonGeometry.createGeometry(polygon); var i = new Cesium.Material({ fabric: { type: "Image", uniforms: { image: this.bottomImg } } }), a = new Cesium.MaterialAppearance({ translucent: !1, flat: !0, material: i }); this.bottomSurface = new Cesium.Primitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: geometry }), appearance: a, asynchronous: !1 }), this.viewer.scene.primitives.add(this.bottomSurface) }}TerrainClipPlan.prototype._createWellWall = function (e, t) { let minHeight = this._getMinHeight(e); let maxHeights = []; let minHeights = []; for (let i = 0; i < t.length; i++) { maxHeights.push(this._ellipsoidToLonLat(t[i]).altitude); minHeights.push(minHeight); } let wall = new Cesium.WallGeometry({ positions: t, maximumHeights: maxHeights, minimumHeights: minHeights, }); let geometry = Cesium.WallGeometry.createGeometry(wall); var a = new Cesium.Material({ fabric: { type: "Image", uniforms: { image: this.wallImg } } }), n = new Cesium.MaterialAppearance({ translucent: !1, flat: !0, material: a }); this.wellWall = new Cesium.Primitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: geometry, attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.GREY) }, id: "PitWall" }), appearance: n, asynchronous: !1 }), this.viewer.scene.primitives.add(this.wellWall)}TerrainClipPlan.prototype._switchExcavate = function (e) { e ? (this.viewer.scene.globe.material = Cesium.Material.fromType("WaJue"), this.wellWall.show = !0, this.bottomSurface.show = !0) : (this.viewer.scene.globe.material = null, this.wellWall.show = !1, this.bottomSurface.show = !1)}TerrainClipPlan.prototype._updateExcavateDepth = function (e) { this.bottomSurface && this.viewer.scene.primitives.remove(this.bottomSurface), this.wellWall && this.viewer.scene.primitives.remove(this.wellWall); for (var t = this.wellData.lerp_pos, i = [], a = t.length, n = 0; n < a; n++) i.push(Cesium.Cartesian3.fromRadians(t[n].longitude, t[n].latitude, this.excavateMinHeight - e)); this.wellData.bottom_pos = i, this._createWell(this.wellData), this.viewer.scene.primitives.add(this.bottomSurface), this.viewer.scene.primitives.add(this.wellWall)}export default TerrainClipPlan 调用 123456789let terrainClipPlan = new TerrainClipPlan(this._viewer._delegate, { height: this._height, splitNum: this._splitNum, wallImg: this._wallImg, bottomImg: this._bottomImg }) console.log(this._hierarchy.positions) terrainClipPlan.updateData(this._hierarchy.positions)","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|三角量测","date":"2020-04-16T12:40:00.000Z","path":"2020/04/16/cesium-量测工具/","text":"效果三角量测 面积量测 线段距离 还有一个圆形面量测 实现量测是地图工具中比较基础的功能,实现也比较容易。三角量测稍微需要研究一点,这里提供思路:1.动态创建三条线段 2.通过直线两端的点计算水平线的另一端坐标 3.动态计算距离并表示 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156/** * 三角测量 */class MeasureTriangles extends Draw { constructor(measureInfo, style) { super(measureInfo) this._tempLineEntity = new Cesium.Entity() this._tempLineEntity2 = new Cesium.Entity() this._positions = [] this._tempPoints = [] this._tempPoints2 = [] this._style = { ...DEF_STYLE, ...style } } _mouseClickHandler(movement) { //let position = this._viewer.delegate.scene.camera.pickEllipsoid(movement.position, Cesium.Ellipsoid.WGS84) let position = this._viewer.scene.pickPosition(movement.position); if(!position)return false if (this._positions.length == 0) { this._positions.push(position.clone()) this._positions.push(position.clone()) this._tempPoints.push(position.clone()) this._tempPoints.push(position.clone()) } } _mouseMoveHandler(movement) { this._viewer.tooltip.setContent('单击选择点位,双击结束') //let position = this._viewer.delegate.scene.camera.pickEllipsoid(movement.endPosition, Cesium.Ellipsoid.WGS84) let position = this._viewer.scene.pickPosition(movement.endPosition); this._viewer.tooltip.setPosition(position) if (position && this._positions.length > 0) { //直线 this._positions.pop() this._positions.push(position.clone()); let horizontalPosition = this._computesHorizontalLine(this._positions) //高度 this._tempPoints.pop() this._tempPoints.push(horizontalPosition.clone()) //水平线 this._tempPoints2.pop(),this._tempPoints2.pop() this._tempPoints2.push(position.clone()) this._tempPoints2.push(horizontalPosition.clone()) } } _getHeading(startPosition, endPosition){ if(!startPosition && !endPosition )return 0 if(Cesium.Cartesian3.equals(startPosition, endPosition))return 0 let cartographic = Cesium.Cartographic.fromCartesian(startPosition); let cartographic2 = Cesium.Cartographic.fromCartesian(endPosition); return (cartographic2.height - cartographic.height).toFixed(2) } _computesHorizontalLine(positions){ let cartographic = Cesium.Cartographic.fromCartesian(positions[0]); let cartographic2 = Cesium.Cartographic.fromCartesian(positions[1]); return Cesium.Cartesian3.fromDegrees( Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude), cartographic2.height ) } _mouseDbClickHandler(movement) { this._unbindEnvet() this._measureEvent.raiseEvent({ type: 'triangles', points: [this._positions,this._tempPoints,this._tempPoints2]}) } _prepareDelegate() { //直线 this._delegate.polyline = { positions: new Cesium.CallbackProperty(time => { return this._positions }, false), ...this._style } this._delegate.position = new Cesium.CallbackProperty(time => { return this._positions[0] }, false), this._delegate.point = { pixelSize: 5, outlineColor: Cesium.Color.BLUE, outlineWidth: 5 } this._delegate.label = { text: new Cesium.CallbackProperty(time => { return '直线:' + CV.Math.getDistance(CV.T.transformCartesianArrayToWSG84Array(this._positions)) + '米' }, false), show: true, showBackground: true, font: '14px monospace', horizontalOrigin: Cesium.HorizontalOrigin.LEFT, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(50, -100) //left top } //高度 this._tempLineEntity.polyline = { positions: new Cesium.CallbackProperty(time => { return this._tempPoints }, false), ...this._style } this._tempLineEntity.position = new Cesium.CallbackProperty(time => { return this._tempPoints2[1] }, false), this._tempLineEntity.point = { pixelSize: 5, outlineColor: Cesium.Color.BLUE, outlineWidth: 5 } this._tempLineEntity.label = { text: new Cesium.CallbackProperty(time => { return '高度:' + this._getHeading(this._tempPoints[0],this._tempPoints[1]) + '米' }, false), show: true, showBackground: true, font: '14px monospace', horizontalOrigin: Cesium.HorizontalOrigin.LEFT, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(-20, 100) //left top } //水平 this._tempLineEntity2.polyline = { positions: new Cesium.CallbackProperty(time => { return this._tempPoints2 }, false), ...this._style } this._tempLineEntity2.position = new Cesium.CallbackProperty(time => { return this._positions[1] }, false), this._tempLineEntity2.point = { pixelSize: 5, outlineColor: Cesium.Color.BLUE, outlineWidth: 5 } this._tempLineEntity2.label = { text: new Cesium.CallbackProperty(time => { return '水平距离:' + CV.Math.getDistance(CV.T.transformCartesianArrayToWSG84Array(this._tempPoints2)) + '米' }, false), show: true, showBackground: true, font: '14px monospace', horizontalOrigin: Cesium.HorizontalOrigin.LEFT, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(-150, -20) //left top } this._layer.entities.add(this._tempLineEntity2) this._layer.entities.add(this._tempLineEntity) this._layer.entities.add(this._delegate) }}export default MeasureTriangles","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium | 可视域分析 2","date":"2020-04-15T10:04:00.000Z","path":"2020/04/15/cesium-可视域分析-2/","text":"效果在之前的可视域分析升级了一下 ~ 可以支持动态修改 实现这里重新写了一个Primitive 需要修改ShadowMapShader.js 123456789fsSource += ' if(visibility>0.5) \\n' + ' { \\n' + ' gl_FragColor = vec4(' + visiblyColor.red + ',' + visiblyColor.green + ',' + visiblyColor.blue + ',' + visiblyColor.alpha + '); \\n' + ' } \\n' + ' else{ \\n' + ' gl_FragColor = vec4(' + invisiblyColor.red + ',' + invisiblyColor.green + ',' + invisiblyColor.blue + ',' + invisiblyColor.alpha + '); \\n' + ' } \\n' + '} \\n';","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|三维可视化展示","date":"2020-04-12T07:24:00.000Z","path":"2020/04/12/cESIU/","text":"前言因工作需要学习cesium有一段时间了,对现有的业务功能进行模块化封装和效果展示。封装完成之后开发一套前端模版,以后项目基本可以基于这个平台做二次开发; 效果展示分为基础功能展示,分析可视化,以及业务功能模块展示 场景控制,地图工具 可视化组件 开源插件 图形插件 控件 地球控制 分析功能 业务封装 ~演示地址私信 前端模版基于封装的sdk的开发模版 集成开源插件,场景控制等 内置8种皮肤 可视域分析 通视分析 环视分析 淹没分析 挖地分析 坡度分析(地形) 基础量测 平台正在完善…","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|传感器效果插件","date":"2020-04-12T06:59:00.000Z","path":"2020/04/12/cesium-传感器动画扫描czml/","text":"效果效果1 矩形传感器 效果2 圆锥传感器 基于czml的动画展示 示例1234567891011121314151617181920212223242526define(function(require) { 'use strict'; var initialize = require('./initialize'); var ConicSensorGraphics = require('./conic/conic-sensor-graphics'); var ConicSensorVisualizer = require('./conic/conic-sensor-visualizer'); var CustomPatternSensorGraphics = require('./custom/custom-pattern-sensor-graphics'); var CustomPatternSensorVisualizer = require('./custom/custom-pattern-sensor-visualizer'); var CustomSensorVolume = require('./custom/custom-sensor-volume'); var RectangularPyramidSensorVolume = require('./rectangular/rectangular-pyramid-sensor-volume'); var RectangularSensorGraphics = require('./rectangular/rectangular-sensor-graphics'); var RectangularSensorVisualizer = require('./rectangular/rectangular-sensor-visualizer'); initialize(); return { ConicSensorGraphics: ConicSensorGraphics, ConicSensorVisualizer: ConicSensorVisualizer, CustomPatternSensorGraphics: CustomPatternSensorGraphics, CustomPatternSensorVisualizer: CustomPatternSensorVisualizer, CustomSensorVolume: CustomSensorVolume, RectangularPyramidSensorVolume: RectangularPyramidSensorVolume, RectangularSensorGraphics: RectangularSensorGraphics, RectangularSensorVisualizer: RectangularSensorVisualizer };}); 开源地址:github地址","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium| Primitive图元自定义着色器(2)","date":"2020-04-12T06:31:00.000Z","path":"2020/04/12/cesium-Primitive图元自定义着色器-1/","text":"效果动态雷达传感器 攻击线 动态扩散点 示例动态雷达传感器开源插件,推荐使用时直接升级添加到项目中 12345678910111213141516171819202122232425262728293031323334import Cesium from "Cesium";import {RectangularSensorPrimitive} from "./RectangularSensor/RectangularSensorPrimitive";import {RectangularSensorGraphics} from "./RectangularSensor/RectangularSensorGraphics";import {RectangularSensorVisualizer} from './RectangularSensor/RectangularSensorVisualizer';//conicSensorimport {ConicArcSensorGeometry} from './ConicArcSensor/ConicArcSensorGeometry';import {ConicArcSensorOutlineGeometry} from './ConicArcSensor/ConicArcSensorOutlineGeometry';import {ConicArcSensorGraphics} from './ConicArcSensor/ConicArcSensorGraphics';import {ConicArcSensorCollection} from './ConicArcSensor/ConicArcSensorCollection';//rectangularSensorCesium.RectangularSensorPrimitive = RectangularSensorPrimitive;Cesium.RectangularSensorGraphics = RectangularSensorGraphics;Cesium.RectangularSensorVisualizer = RectangularSensorVisualizer;//conicSensorCesium.ConicArcSensorGeometry = ConicArcSensorGeometry;Cesium.ConicArcSensorOutlineGeometry = ConicArcSensorOutlineGeometry;Cesium.ConicArcSensorGraphics = ConicArcSensorGraphics;Cesium.ConicArcSensorCollection = ConicArcSensorCollection;var DataSourceDisplay = Cesium.DataSourceDisplay;var originalDefaultVisualizersCallback = DataSourceDisplay.defaultVisualizersCallback;DataSourceDisplay.defaultVisualizersCallback = function (scene, entityCluster, dataSource) { var entities = dataSource.entities; var array = originalDefaultVisualizersCallback(scene, entityCluster, dataSource); return array.concat([ new RectangularSensorVisualizer(scene, entities) ]);}; 支持升级到1.5X ,如需升级到1.6更改import导入方式,不支持直接导入。 开源地址:github地址","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|通视分析","date":"2020-04-12T06:19:00.000Z","path":"2020/04/12/cesium-通视分析/","text":"效果通视分析是指以某一点为观察点,研究某一区域通视情况的地形分析。 示例通过cesium提供的碰撞检测api获取障碍点实现同时分析 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133import PointDrawer from '../../BaseTool/Draw/DrawPoint';import LineDrawer from '../../BaseTool/Draw/DrawLine';import Coordinate from '../../BaseTool/Coordinate';import Cesium from 'Cesium'export default class InterAnalysis { // viewer: any; // interAnalysis_map: Map<Symbol, any>; // lineEntities: any = []; // pointEntities: any[] = []; constructor(viewer) { this.viewer = viewer; this.interAnalysis_map = new Map(); this.pointEntities = []; this.lineEntities = []; } create(sPoint, ePoint, objId) { debugger if (ePoint.x === sPoint.x && ePoint.y === sPoint.y && ePoint.z === sPoint.z) { this.pointEntities.push(PointDrawer.draw(this.viewer, sPoint, 10, Cesium.Color.AQUAMARINE)); console.warn('通视起点与终点重叠'); return; } this.pointEntities.push(PointDrawer.draw(this.viewer, sPoint, 10, Cesium.Color.AQUAMARINE)); this.pointEntities.push(PointDrawer.draw(this.viewer, ePoint, 10, Cesium.Color.AQUAMARINE)); let obj = this.drawVisibility(sPoint, ePoint).then((obstaclePoint) => { //获取视觉障碍点, 绘制线段 if (!obstaclePoint) { obstaclePoint = ePoint; debugger return; } this.lineEntities.push(LineDrawer.draw(this.viewer, [sPoint, obstaclePoint], Cesium.Color.GREEN)); this.lineEntities.push(LineDrawer.draw(this.viewer, [obstaclePoint, ePoint], Cesium.Color.RED)); }); this.interAnalysis_map.set(objId, obj); } //绘制通视线 drawVisibility(sPoint, ePoint) { var promise = Cesium.when.defer(); var removePreRenderListener = this.viewer.scene.postUpdate.addEventListener(() => { //设置相机 var curCamera = this.setCameraPositoion(sPoint, ePoint); var removePostRenderListener = this.viewer.scene.postRender.addEventListener(() => { //取点 var obstaclePoint = this.getObstaclePoint(ePoint); //重置相机 this.resetCamera(curCamera); removePreRenderListener(); var removeOverlayListener = this.viewer.scene.postRender.addEventListener(function() { removeOverlayListener(); }); promise.resolve(obstaclePoint); removePostRenderListener(); }); }); return promise; } //设置相机位置 setCameraPositoion(sPoint, ePoint) { let curCamera = { positon: this.viewer.camera.position.clone(), direction: this.viewer.camera.direction.clone(), up: this.viewer.camera.up.clone() }; let direction = this.calculateDirection(sPoint, ePoint); let location = Coordinate.cartesian2lonlat(sPoint); let position1 = Cesium.Cartesian3.fromDegrees(location.longitude, location.latitude, location.height + 0.1); this.viewer.camera.setView({ destination: position1, orientation: { direction: direction, up: this.viewer.camera.up.clone() } }); return curCamera; } //获取障碍点 getObstaclePoint(ePoint) { let screenLocation = this.viewer.scene.cartesianToCanvasCoordinates(ePoint); if (!screenLocation) { console.warn('获取屏幕坐标失败'); return ePoint; } let obstaclePoint = this.viewer.scene.pickPosition(screenLocation); return obstaclePoint; } //重置相机 resetCamera(camera) { this.viewer.camera.setView({ destination: camera.positon, orientation: { direction: camera.direction, up: camera.up } }); } //计算方向 calculateDirection(p1, p2) { return Cesium.Cartesian3.normalize( Cesium.Cartesian3.subtract(p2, p1, new Cesium.Cartesian3()), new Cesium.Cartesian3() ); } //清除绘制 clearDraw() { if (this.pointEntities.length > 0) { for (let i = 0; i < this.pointEntities.length ; i++) { this.viewer.entities.removeById(this.pointEntities[i].id); } } if (this.lineEntities.length > 0) { for (let _i = 0; _i < this.lineEntities.length; _i++) { this.viewer.entities.removeById(this.lineEntities[_i].id); } } }} 该示例只是将碰撞点的位置截取出来,渲染成两种颜色,还可以进一步添加分析结果和环视分析。 开源地址:github地址","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|可视域分析","date":"2020-04-12T05:53:00.000Z","path":"2020/04/12/cesium-可视域分析实现/","text":"效果可视域在三维中是比较常用的分析功能,很多领域中都能应用到。 示例创建起终点,模拟相机的视锥绘制视锥体,创建点光源添加阴影效果。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182import Coordinate from '../../BaseTool/Coordinate';import Cesium from 'Cesium'import PointDrawer from '../../BaseTool/Draw/DrawPoint';export default class Viewshed { // viewer: any; // vishedfrustum: any = null; // pointEntities: any[] = []; constructor(viewer) { this.viewer = viewer; this.pointEntities = []; } init(pointArr) { if(pointArr.length === 1){ this.pointEntities.push(PointDrawer.draw(this.viewer, pointArr[0], 10, Cesium.Color.AQUAMARINE)) } else if(pointArr.length === 2){ this.pointEntities.push(PointDrawer.draw(this.viewer, pointArr[0], 10, Cesium.Color.AQUAMARINE)); this.pointEntities.push(PointDrawer.draw(this.viewer, pointArr[1], 10, Cesium.Color.AQUAMARINE)); this.createViewshedMap(pointArr[0], pointArr[1]); } } exit() { //clear point arr this.pointEntities.forEach(item => { this.viewer.entities.remove(item); }); this.pointEntities = []; //stop shadowMap // PopCity.viewer.scene.shadowMap.enabled = false; //clear primitive if (this.vishedfrustum) { this.viewer.scene.primitives.remove(this.vishedfrustum); this.vishedfrustum = false; } this.viewer.scene.primitives._primitives.forEach((item, index) => { if (item.name === 'VIEWSHEDPRIMITIVE') { this.viewer.scene.primitives._primitives.splice(index, 1); } }); } //核心代码 createViewshedMap(start, end) { var scene = this.viewer.scene; var spotLightCamera = new Cesium.Camera(scene); spotLightCamera.position = start; spotLightCamera.direction = this.calculateDirection(start, end); spotLightCamera.up = Cesium.Cartesian3.clone(this.viewer.camera.up); spotLightCamera.frustum.fov = Cesium.Math.PI_OVER_THREE; spotLightCamera.frustum.near = 0.1; spotLightCamera.frustum.far = Cesium.Cartesian3.distance(start, end); //绘制视锥体 this.drawFrustum(start, end, spotLightCamera.frustum); var viewshedOptions = { context: scene.context, lightCamera: spotLightCamera, cascadesEnabled: false, softShadows: true, viewshed: true }; var viewshed = new Cesium.ShadowMap(viewshedOptions); viewshed.enabled = true; viewshed.size = 1024; // const ViewshedPrimitive = function(this, shadowMap) { // this.shadowMap = shadowMap; // this.name = 'VIEWSHEDPRIMITIVE'; // } // var that = this; const ViewshedPrimitive = function(shadowMap) { this.shadowMap = shadowMap; this.name = 'VIEWSHEDPRIMITIVE'; }; ViewshedPrimitive.prototype.update = function(frameState) { frameState.shadowMaps.push(this.shadowMap); }; scene.primitives.add(new ViewshedPrimitive(viewshed)); } //计算方向 calculateDirection(p1, p2) { return Cesium.Cartesian3.normalize( Cesium.Cartesian3.subtract(p2, p1, new Cesium.Cartesian3()), new Cesium.Cartesian3() ); } drawFrustum(position1, position2, frustum) { var orientation = this.calculateorigntation(position1, position2); var primitive = new Cesium.Primitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: new Cesium.FrustumOutlineGeometry({ frustum: frustum, origin: position1, orientation: orientation }), attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 0.0, 1.0)) } }), appearance: new Cesium.PerInstanceColorAppearance({ flat: true }) }); this.viewer.scene.primitives.add(primitive); this.vishedfrustum = primitive; } calculateorigntation(p1, p2) { var co1 = Coordinate.cartesian2lonlat(p1); var co2 = Coordinate.cartesian2lonlat(p2); var width = Coordinate.catchDistancefromCartographic2D( co1.longitude, co1.latitude, co2.longitude, co1.latitude ); var length = Coordinate.catchDistancefromCartographic2D( co1.longitude, co1.latitude, co1.longitude, co2.latitude ); var height = co1.height - co2.height; var distance = Coordinate.catchDistancefromCartographic2D( co1.longitude, co1.latitude, co2.longitude, co2.latitude ); var angle = Math.atan(width / length); var tilt = Math.atan(height / distance); if (co1.latitude > co2.latitude) { angle = Math.PI - angle; } if (co1.longitude > co2.longitude) { angle = -angle; } var heading = angle; var pitch = 0; var roll = -Math.PI / 2 - tilt; var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll); var orientation = Cesium.Transforms.headingPitchRollQuaternion(p1, hpr); return orientation; } clearDraw() { //清除点 if (this.pointEntities && this.pointEntities.length > 0) { for (var i = 0; i < this.pointEntities.length ; i++) { this.viewer.entities.remove(this.pointEntities[i]); // pointArr.splice(i,1); } } //清除视锥 if (this.vishedfrustum) { this.viewer.scene.primitives.remove(this.vishedfrustum); } //清除阴影 this.viewer.scene.primitives._primitives.forEach((item, index) => { if (item.name === 'VIEWSHEDPRIMITIVE') { this.viewer.scene.primitives._primitives.splice(index, 1); } }); }} 实现效果比较粗糙 开源地址:github地址","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"Vue|父子组件的通信","date":"2020-04-11T14:19:00.000Z","path":"2020/04/11/Vue/","text":"方式ref: 父组件中调用子组件的方法并向子组件传参。 emit: 子组件触发父组件的方法并传递参数。 props: 父组件向子组件动态传值。 示例refref 在元素或自组件中标记能访问的对象。 12345678910111213141516171819202122232425262728293031323334353637<template> <div> <p ref="p">ref-test</p> </div></template><script> export default { data() { return {} }, mounted() { console.log(this.$refs.p) } }</script><template> <div> <p ref="p">ref-test</p> </div></template><script> export default { data() { return {} }, mounted() { console.log(this.$refs.p) } }</script>//父组件文件//引入组件<com ref="com"></com>//打印数据console.log(this.$refs.com) 1 这里我们只能取到组件的值或调用方法,不可以通过这个方法改变组件的相关属性值。2 因为ref本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs也不是响应式的,因此不可以用它在模板中做数据绑定。 emit和props1、父组件可以使用 props 把数据传给子组件。 2、子组件可以使用 $emit 触发父组件的自定义事件。 vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( event, fn );//监听event事件后运行 fn; 子组件 1234567891011121314151617181920<template> <div class="train-city"> <h3>父组件传给子组件的toCity:{{sendData}}</h3> <br/><button @click='select(`大连`)'>点击此处将‘大连’发射给父组件</button> </div> </template> <script> export default { name:'trainCity', props:['sendData'], // 用来接收父组件传给子组件的数据 methods:{ select(val) { let data = { cityname: val }; this.$emit('showCityName',data);//select事件触发后,自动触发showCityName事件 } } } </script> 父组件 12345678910111213141516171819202122<template> <div>父组件的toCity{{toCity}}</div> <train-city @showCityName="updateCity" :sendData="toCity"></train-city> <template> <script> import TrainCity from "./train-city"; export default { name:'index', components: {TrainCity}, data () { return { toCity:"北京" } }, methods:{ updateCity(data){//触发子组件城市选择-选择城市的事件 this.toCity = data.cityname;//改变了父组件的值 console.log('toCity:'+this.toCity) } } } </script> 传递参数需要: 12345671、传递参数时要用—代替驼峰命名,HTML不区分大小写2、sendProp要在父组件的data中定义,例如 sendProp:''3、messageProp在子组件的props中声明类型,例如 messageProp: String4、在利用props实现传值的过程中理论上是要实现单向传递,即父组件改变相关参数的值,子组件也相应变化,但是子组件对参数的改变不应该影响父组件。但是当props中接收的是父组件传递的引用类型(对象或者是数组)时,在子组件中对数据改变时,父组件中的数据也会相应的改变,因为两者是指向的同一地址内存。如果不想子组件的改变影响父组件可以利用深拷贝,将接受的数据进行深拷贝后在子组件中使用,而不直接操作接受的数据。 vue常用组件:https://www.jianshu.com/p/c9b3df751f36?utm_campaign=haruki vue通用组件封装:https://www.jianshu.com/p/233d17dfbd16","tags":[{"name":"vue","slug":"vue","permalink":"http://yoursite.com/tags/vue/"}]},{"title":"cesium|多线程的实现","date":"2020-04-11T13:48:00.000Z","path":"2020/04/11/cesium-多线程的实现/","text":"Web Worker什么是 web worker js本身是一种单线程设计,我们无法在同一时刻并行运行多个脚本。虽然可以用setInterval,setTimeout方法来模拟多线程,但实际上这些方法都是存在于主线程使用的一个事件循环里,一旦存在一个耗时操作,就会牵制主线程的操作,导致页面卡顿。 Web Worker通过引入类似线程的机制使这种问题得到了解决,通过在当前js主线程中使用worker类加载一个js文件来开辟一个新线程,起到互不阻塞执行的效果。这个js worker运行在另一个全局上下文中,不同于当前的window,所以不能用window变量来获取当前全局的范围。 什么时候使用 1 当需要一个js脚本进行大量的复杂计算时候,通过postMessage和onmessage进行通信 2 功能模块化。importScripts这个方法只能在worker线程中执行,该方法可以在worker线程中引入多个脚本,则该线程可以使用所引入脚本中的任意变量和函数。 3 当需要执行一个不断向后台发送更新请求的时候,可以将这个过程放到工作线程里,然后将结果返回给主线程。 如何使用 ①创建一个线程:通过new一个Worker实例来创建一个线程,构造函数参数传递一个指向js文件资源的url。const worker = new Worker('a.js') ②与一个线程通信:主线程 1234567onload =function(){ var worker =new Worker('a.js'); worker.onmessage = function (evt) {//接收子线程消息 console.log(evt.data); //hello received }; worker.postMessage("hello")//向子线程发送消息} 子线程 1234onmessage =function(event) { //接收主线程消息 let str = event.data; postMessage(str+" received"); //发送子线程消息}; 在主线程中,消息事件依托于创建出来的worker对象,而在工作线程中,消息事件依托于全局对象。 当工作线程完成了任务后,需要调用terminate方法来释放内存和避免僵尸线程的情况:worker.terminate(); cesium实现的多线程如何使用: 1 用户只需要创建一个TaskProcessor,指定具体需要创建线程的类型 :圆 2 然后调用scheduleTask,里面是该对象的具体参数 : 圆position + 半径 3 处理结果通过promise机制返回一个异步对象,方便用户使用 cesium设计的多线程会通过创建TaskProcessor指定参数给scheduleTask最后计算通过Promise机制返回异步处理。内部通过require关联对应的功能函数,并替换onmessage函数。 cesium的底层实现 : 原理篇 : https://www.cnblogs.com/fuckgiser/p/5869122.html","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium| PostProcessStage后期处理","date":"2020-04-10T10:24:00.000Z","path":"2020/04/10/cesium-postProcessStages后期处理添加特效/","text":"前言cesium中提供了postProceSsstagge接口,能在三维场景中添加后期渲染效果。处理对包括模型描边、黑白图、明亮度调整、夜视效果、环境光遮蔽。 原理篇:https://www.cnblogs.com/webgl-angela/p/9272810.html 后期处理原理图 后期处理的过程有点类似于照片的PS。生活中拍摄了一张自拍照,看到照片后发现它太暗了,于是我们增加亮度得到了一张新的照片。在增加亮度后发现脸上的痘痘清晰可见,这可不是我们希望的效果,于是再进行一次美肤效果处理。在这之后可能还会进行n次别的操作,直到满足我们的要求。上述这个过程和三维里面的后期处理流程非常类似:拍的原始照片相当于三维场景中实际渲染得到的效果,在此基础上进行物体描边、夜视效果、环境光遮蔽等后期处理,最后渲染到场景中的图片相当于定版的最终照片。 总结 : 后期处理其实是一个叠加修改的过程,通过不同步骤的加工,最后得到想要的结果 处理流程:PostProcessStage主要相关接口: PostProcessStage:对应于某个具体的后期处理效果,它的输入为场景渲染图或者上一个后期处理的结果图,输出结果是一张处理后的图片。 PostProcessStageComposite:一个集合对象,存储类型为PostProcessStage或者PostProcessStageComposite的元素。 PostProcessStageLibrary:负责创建具体的后期处理效果,包括Silhouette、Bloom、AmbientOcclusion等,创建返回的结果是PostProcessStageComposite或者PostProcessStage类型。 PostProcessStageCollection:是一个集合类型的类,负责管理和维护放到集合中的元素 ,元素的类型是PostProcessStage或者PostProcessStageComposite。 添加后期效果流程: 1 通过PostProcessStageLibrary创建一个或者多个后处理效果对象,得到多个PostProcessStage或者PostProcessStageComposite。2 将他们加入到PostProcessStageCollection对象中。这样PostProcessStageCollection对象就会按照加入的顺序进行屏幕后期处理,在所有的效果都处理完毕后,执行FXAA,3 绘制到屏幕上。 示例添加场景亮度添加片段着色器,调整纹理颜色放大系数实现亮度调整 1234567891011121314151617181920var fs = 'uniform sampler2D colorTexture;\\n' + 'varying vec2 v_textureCoordinates;\\n' + 'uniform float scale;\\n' + 'uniform vec3 offset;\\n' + 'void main() {\\n' + ' vec4 color = texture2D(colorTexture, v_textureCoordinates);\\n' + //获取片段颜色 ' gl_FragColor = vec4(color.rgb * scale + offset, 10.0);\\n' + '}\\n'; //放大片段颜色系数 viewer.scene.postProcessStages.add(new Cesium.PostProcessStage({ fragmentShader: fs, uniforms: { scale: 1.1, offset: function () { // return new Cesium.Cartesian3(0.1, 0.2, 0.3); return new Cesium.Cartesian3(0.01, 0.02, 0.03); } } })); 效果 添加雾气粒子效果:csdn博客 添加一个动态扩散圆:csdn博客","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium| Primitive图元自定义着色器(1)","date":"2020-04-10T07:21:00.000Z","path":"2020/04/10/cesium-primitive图元自定义着色器/","text":"前言Primitive是cesium核心api之一,与entity方式绘制方式(基于数据)不同,primitive更接近渲染引擎底层。entity适合以数据绘制实体,而primitive更适合图形学对有webgl经验的更亲和。primitive绘制的图形比entity添加的实体性能更好,webgl特性使primitive能绘制更多样式的图形。 对entity和primitive与scene之间的关联可以参考 【cesiumAPI笔记篇】 Primitive特性 1234567891011121 由两部分组成(1)几何形状(Geometry):定义了Primitive的结构,例如三角形、线条、点等(2)外观(Appearance ):定义Primitive的着色(Sharding),包括GLSL(OpenGL着色语言,OpenGL ShadingLanguage)顶点着色器和片段着色器( vertex and fragment shaders),以及渲染状态(render state)2 使用Geometry和Appearance 具有以下优势:(1)性能:绘制大量Primitive时,可以将其合并为单个Geometry以减轻CPU负担、更好的使用GPU。合并Primitive由web worker线程执行,UI保持响应性(2)灵活性:Geometry与Appearance 解耦,两者可以分别进行修改(3)低级别访问:易于编写GLSL 顶点、片段着色器、使用自定义的渲染状态3 同时具有以下劣势:(1)需要编写更多地代码(2)需要对图形编程有更多的理解,特别是OpenGL的知识 Primitive详解 :https://www.jianshu.com/p/5a74c607a591 示例数据准备1234567891011121314//雷达的高度var length = 400000.0;//地面位置(垂直地面) var positionOnEllipsoid = Cesium.Cartesian3.fromDegrees(116.39, 39.9);//中心位置var centerOnEllipsoid = Cesium.Cartesian3.fromDegrees(116.39, 39.9, length*0.5);// 顶部位置(卫星位置)var topOnEllipsoid = Cesium.Cartesian3.fromDegrees(116.39, 39.9,length);//矩阵计算var modelMatrix = Cesium.Matrix4.multiplyByTranslation( //转换矩阵 Cesium.Transforms.eastNorthUpToFixedFrame(positionOnEllipsoid), //矩阵 new Cesium.Cartesian3(0.0, 0.0, length * 0.5), //要转换的笛卡尔坐标 new Cesium.Matrix4() //返回新的矩阵 ); Geometry创建一个圆锥几何图形 12345678910111. 构造geometryvar cylinderGeometry = new Cesium.CylinderGeometry({ length: length, topRadius: 0.0, bottomRadius: length * 0.5, vertexFormat: Cesium.MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat});2. 创建GeometryInstancevar redCone = new Cesium.GeometryInstance({ geometry: cylinderGeometry, //geomtry类型 modelMatrix: modelMatrix, //模型矩阵 调整矩阵的位置和方向}); shader着色器定义glsl代码 1234567891011121314151617181920let source =//传入的动态数值`uniform vec4 color; uniform float repeat; uniform float offset; uniform float thickness;//设置图形外观材质czm_material czm_getMaterial(czm_materialInput materialInput){ czm_material material = czm_getDefaultMaterial(materialInput); //获取内置的默认材质 float sp = 1.0/repeat; //重复贴图 vec2 st = materialInput.st; //二维纹理坐标 float dis = distance(st, vec2(0.5)); //计算距离 float m = mod(dis + offset, sp); //间隔 float a = step(sp*(1.0-thickness), m);//线条拼色 //修改材质 material.diffuse = color.rgb; material.alpha = a * color.a; return material;}` 自定义shader着色器 和 Material :https://www.cnblogs.com/fuckgiser/p/6171245.html appearance自定义material外观材质,修改着色器 12345678910111213let material = new Cesium.Material({ fabric: { type: 'VtxfShader1', uniforms: { //动态传递参数 color: new Cesium.Color(0.2, 1.0, 0.0, 1.0), repeat: 30.0, offset: 0.0, thickness: 0.3, }, source :source }, translucent: false}) 定义appearance外观 12345let appearance = new Cesium.MaterialAppearance({ material:material,//自定义的材质 faceForward : false, // 当绘制的三角面片法向不能朝向视点时,自动翻转法向, 从而避免法向计算后发黑等问题 closed: true // 是否为封闭体,实际上执行的是是否进行背面裁剪}) 创建Primitive创建自定义primitive图元,实现动态效果 12345678910111213141516//添加Primitive var radar = viewer.scene.primitives.add( new Cesium.Primitive({ geometryInstances: [redCone], appearance:appearance })); //动态修改雷达材质中的offset变量,从而实现动态效果。 viewer.scene.preUpdate.addEventListener(function() { var offset = radar.appearance.material.uniforms.offset; offset -= 0.001; if (offset > 1.0) { offset = 0.0; } radar.appearance.material.uniforms.offset = offset; }) 效果","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"随笔|cesium的Entity动态效果实现","date":"2020-04-10T03:55:00.000Z","path":"2020/04/10/随笔-cesium实体动态效果实现/","text":"前言前面讲了cesium的API学习大概思路,对一些api不是很了解的可以基于那个框架去延伸。这路在看下cesium中对实体动态修改提供的内置对象 property 原理篇 博客园 :https://www.cnblogs.com/yanan-boke/p/7447997.html vxtf简书 :https://www.jianshu.com/p/f0b47997224c 随笔借图 cesium中每一个entity属性都是一个property实例,实例提供了基本的属性方法getValue,setValue以及equals。基于property基类提供positionProperty,materialProperty等拓展类,实现了更多效果和衍生。 Entity封装属性示例 :Cesium中提供了defineProperties方法,继承Object.defineProperties新版cesium改成使用Object。 12345678910111213141516171819202122232425262728function Entity(options) { var id = options.id; if (!defined(id)) { id = createGuid(); } this._id = id; this._name = options.name; this._description = undefined; this._position = undefined; this._rectangle = undefined;}// Key 1:definePropertiesdefineProperties(Entity.prototype, { id : { get : function() { return this._id; } }, // Key 2:createRawPropertyDescriptor name : createRawPropertyDescriptor('name'), // Key 3:createPropertyDescriptor description : createPropertyDescriptor('description'), // Key 4:createPositionPropertyDescriptor position : createPositionPropertyDescriptor('position'), // Key 5:createPropertyTypeDescriptor rectangle : createPropertyTypeDescriptor('rectangle', RectangleGraphics)}); Cesium中的成员变量和属性方法之间就是一个下划线_,比如成员变量为_id,对应的属性方法为id,这是Cesium中的一个规范。 PropertyProperty基本类型: 区分:Property都是可以赋值给Entity的任意属性实例。 SampleProperty :用来通过给定多个不同时间点的Sample,然后在每两个时间点之间进行线性插值的一种Property TimeIntervalCollectionProperty :该Property用来指定各个具体的时间段的属性值,每个时间段内的属性值是恒定的,并不会发生变化,除非已经进入到下一个时间段 ConstantProperty:最常用的property,cesium在给实体赋值自动将数值转换成property实例:enity.box.dimensions = new ConstantProperty(new Cesium.Cartesian3(400000.0, 300000.0, 200000.0)); CompositeProperty : 可以把多种不同类型的ConstantProperty、SampleProperty、TimeIntervalCollectionProperty等Property组合在一起来操作。比如前一个时间段需要线性运动,后一段时间再跳跃式运动 PositionProperty类型 : 内置的接口和property的基本接口作用一样,作用于position的 区分:不可实例化,只能用来表示position,拓展property接口 SampledPositionProperty:同SampleProperty作用一样,多了一个位置插值setInterpolationOptions用来表示不同差值的类型:线性插值,Lagrange插值,Hermite插值。 MaterialProperty类型: 作用于Material外观材质的,基本材质的property接口。 区分:只能用来表示Material,拓展property接口 ColorMaterialProperty 示例: 123456789var colorProperty = new Cesium.SampledProperty(Cesium.Color); colorProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), new Cesium.Color(0, 1, 0)); colorProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), new Cesium.Color(0, 0, 1)); blueBox.box.material = new Cesium.ColorMaterialProperty(colorProperty); 其他类型的Property: CallbackProperty :是自由度最高的一种Property,让用户通过自定义,回调函数,来返回需要的值。回调函数中,用户可以使用time来给定value,也可以以自己的方式给给定。 ReferenceProperty : 该Property可以直接链接到别的对象的Property上,相当于引用,省得自己构建了。比如这里我创建了一个红色的盒子redBox,希望它和之前的蓝色盒子一起变大 PropertyBag :可以包装一个对象(JS中的对象概念),该对象的每一个属性(JS中的属性概念),都可以作为一个动态的Property。 PropertyArray : 包装一个对象,内部封装了一个数组。 VelocityOrientationProperty :该Property用来Entity的position的位置变化,来计算出移动的方向,最后把速度方向输出成Orientation。这里可以实现动态路径绑定跟踪扫描物体。 VelocityVectorProperty :和VelocityOrientationProperty一样,不过是速度方向输出成一个预设的Vector。","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"随笔|cesiumAPI笔记","date":"2020-04-10T02:34:00.000Z","path":"2020/04/10/cesium-温习API/","text":"前言学习cesium有一段时间了,也做了几个三维项目。但每次翻Api时感觉了解的还是不够深,只是基于上层Api的调用,感叹cesium水太深不愧是一群研究数学和图形的大佬写的,在此之前还真得把webgl好好补补。 Cesium原理篇 法克鸡丝博客园:https://www.cnblogs.com/fuckgiser/p/5706842.html Cesium Api学习指南 vxtf简书: https://www.jianshu.com/p/9a71186edd5b 随笔借图 学习cesium时可以根据这个结构去延伸 viewer :三维窗口元素集合,所有组件对象的入口。管理组件和api对象使用 cesiumWidget :三维窗口,创建所需有的元素包含scene管理三维场景对象,学习过webgl的想必不会陌生。canvas画布对象还有clock时钟对象等组成。container三维窗口创建挂载的容器。screenSpaceEvenHandler三维窗口的事件类,封装了鼠标,手势等基本事件。 dataSourceDisplay : viewer向三维场景中添加三维对象的接口。所有外部数据源管理的入口。dataSourceDisplay添加完外部数据之后会关联到scene三维场景中,操作修改数据相应也会修改三维场景的关联对象。defaultDataSource相当于内置dataSource,添加实体只需要viewer.entities无需手动创建,底层是使用dataSourceDisplay.defaultDataSource.entities,其他数据源对象则需要另外添加。 UI组件 : 三维窗口的ui组件集合,都可以通过viewer.xx来调用管理。 scene :三维场景对象。三维场景包含globe地球类,地球表皮影像和地形数据的渲染。primitives表示加入三维场景中的各种三维对象。groundPrimitives用来表示贴地的三维对象。viewer.entities加入场景中的三维实体,大多会转化成primitives和groundPrimitives。 primitive:三维场景中的一个基本绘制图元对象。primitive提供更多的图形绘制功能,可以自定义图元类型和外观。使用着色器渲染图形对象,使用shader定制更好的效果。 entity : 三维实体,cesium基于数据的封装,对图形不是很了解的学习者很友善。基于entity的动态效果cesium提供了Property对象。 以上就是cesium的大体结构,具体的scene和dataSourceDisplay的数据关联可以参考vxtf的博客。","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|三维标绘工具","date":"2020-04-08T09:29:00.000Z","path":"2020/04/08/cesium-三维标绘工具/","text":"示例图形标绘 军事标绘 动态标绘 功能正在完善… 实现1234567891011121314151617181920212223242526272829303132import DrawDynamicTool from './DrawDynamicTool';import DrawMilitaryTool from './DrawMilitaryTool';export default class PlotHelper{ constructor(core){ this.viewe = core; //初始化 this.initPlot() } //初始化标绘控件 initPlot(){ //图形标绘 this.DrawDynamicTool = new DrawDynamicTool(this.viewe); //军事标绘 this.DrawMilitaryTool = new DrawMilitaryTool(this.viewe); } //绘制 draw(cmd,type){ if(!cmd)return false; switch(cmd){ case "图形" : this.DrawDynamicTool.draw(type);break; case "军事" : this.DrawMilitaryTool.draw(type);break; case "特殊" : break; } } //清除 clear(){ this.DrawMilitaryTool.clearAll(); this.DrawDynamicTool.remove(); }} 代码篇幅过长 DrawDynamicTool 和 DrawMilitaryTool在github示例上 三维可视化:博客","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"excel|数据处理之自动排序自动加载","date":"2020-04-08T09:14:00.000Z","path":"2020/04/08/excel-数据处理之自动排序自动加载/","text":"前言在处理数据时,如果量级不是很大的话,excel的数据透视表比mysql之类的数据库要方便很多,这里通过数据透视筛选完成之后进行动态展示。 效果制作下拉选自动排序使用 VLOOKUP() ,HLOOKUP(),RANK() 函数 准备一份数据源表 新建一个sheet,创建城市数据表 1 将城市选项制作成下拉格式:数据-数据有效性-序列-选在范围(数据源表的城市行) 2 feature和变量名直接从数据源表按顺序复制过来 3 第四列的逻辑:=HLOOKUP(D1,数据表!C1:LD27,2,0) 列名是上海的第二个数。然后依次往下 4 第一列逻辑:=RANK(D2,$D$2:$D$27) 第四列从大到小的排名 自动排序表 1)第一列 手动输入top1-20 2)使用 VLOOKUP()函数将城市数据表中对应的序号匹配过来 3)完成自动排序 可动态选择查看数据并列出top10,top20的列","tags":[{"name":"excel","slug":"excel","permalink":"http://yoursite.com/tags/excel/"}]},{"title":"excel| 数据分析之变量相关性分析","date":"2020-04-08T09:05:00.000Z","path":"2020/04/08/excel-数据分析之相关性系数分析/","text":"前言之前项目需要,在数据分析这块学习了一段时间,使用excel的数据分析高级功能对模型预测出来的数据和统计年鉴的数据做了一下相关性分析。 准备 准备预测好的数据和统计年鉴的数据 使用excel并拓展数据分析工具 选择excel数据加载项 勾选数据分析并使用 分析数据分析 - 相关系数 - 选择输入范围 - 输出范围 点击确认计算出相关R值 :R值0.4~0.6属于弱相关 计算R方:插入散点图 - 添加线性 - - 显示公式和R方 说明 : python可以直接用pandas的矩阵相关系数corr()输出","tags":[{"name":"excel","slug":"excel","permalink":"http://yoursite.com/tags/excel/"}]},{"title":"cesium|三维分析功能","date":"2020-04-07T08:34:00.000Z","path":"2020/04/07/cesium-三维分析功能/","text":"示例概览 测控分析 过境分析 实现部分代码重构完善中… 三维量测功能:csdn地址 (未重构)","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|三维风场插件","date":"2020-04-07T08:24:00.000Z","path":"2020/04/07/cesium-三维风场插件/","text":"效果 实现支持.nc数据上图 根据项目改动 轮子地址: github地址","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|基于dat的场景控制控件","date":"2020-04-07T08:13:00.000Z","path":"2020/04/07/cesium-基于dat的场景控制控件/","text":"示例 实现基于dat.GUI的场景控件 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104let sceneTree = new SceneTree(viewer); let Options = function () { this.fog = true; this.lighting = false; this.lensFlare = false; this.groundAtmosphere = true; this.rain = false; this.snow = false; this.sun = true; this.skyBox = true; this.globe = true; this.sbstyle = false; this.depthTestAgainstTerrain = false; this.rotation = false; this.grid = false; this.tileGrid = false; this.mgrsGrid = false; this.navi = true; this.timeLine = false; this.info = false; this.sbjk = true; this.cesiumTool = false; this.radar = false; this.province = false; this.terrain = false; this.tiles = false; this.btnCut = function () { Config.cutScene(viewer); }; } let option = new Options(); let gui = new dat.GUI(); gui.__closeButton.innerHTML = "收缩面板"; gui.add(option, 'fog').name("雾天").onChange(function (value) { sceneTree.build({ "fog": value }); }) gui.add(option, 'lighting').name("昼夜").onChange(function (value) { sceneTree.build({ "lighting": value }); }) gui.add(option, 'lensFlare').name("光晕").onChange(function (value) { lensFlare.enabled = value; }) gui.add(option, 'groundAtmosphere').name("大气层").onChange(function (value) { sceneTree.build({ "groundAtmosphere": value }); }) gui.add(option, 'rain').name("雨天").onChange(function (value) { sceneTree.build({ "rain": value }); }) gui.add(option, 'snow').name("雪天").onChange(function (value) { sceneTree.build({ "snow": value }); }) gui.add(option, 'sun').name("太阳").onChange(function (value) { viewer.scene.sun.show = value; }) gui.add(option, 'skyBox').name("星空").onChange(function (value) { viewer.scene.skyBox.show = value; }) gui.add(option, 'globe').name("地球").onChange(function (value) { viewer.scene.globe.show = value; }) gui.add(option, 'sbstyle').name("鼠标十字").onChange(function (value) { sceneTree.build({ "sbstyle": value }); }) gui.add(option, 'depthTestAgainstTerrain').name("深度检测").onChange(function (value) { viewer.scene.globe.depthTestAgainstTerrain = value; }) gui.add(option, 'rotation').name("地球自转").onChange(function (value) { sceneTree.build({ "rotation": value }); }) gui.add(option, 'grid').name("经纬网").onChange(function (value) { sceneTree.build({ "grid": { "cmd": 1, "flag": value } }); }) gui.add(option, 'tileGrid').name("标注网格").onChange(function (value) { sceneTree.build({ "grid": { "cmd": 2, "flag": value } }); }) gui.add(option, 'mgrsGrid').name("军事网格").onChange(function (value) { sceneTree.build({ "grid": { "cmd": 3, "flag": value } }); }) gui.add(option, 'navi').name("导航插件").onChange(function (value) { sceneTree.build({ "navi": value }); }) gui.add(option, 'timeLine').name("时间轴").onChange(function (value) { sceneTree.build({ "sjz": value }); }) gui.add(option, 'sbjk').name("鼠标位置").onChange(function (value) { sceneTree.build({ "xjzt": value }); }) gui.add(option, 'cesiumTool').name("内置工具").onChange(function (value) { sceneTree.build({ "cesiumTool": value }); }) gui.add(option, 'radar').name("全球雷达站").onChange(function (value) { sceneTree.build({ "radar": value }); }) gui.add(option, 'province').name("全国省份").onChange(function (value) { sceneTree.build({ "province": value }); }) gui.add(option, 'terrain').name("地形图").onChange(function (value) { sceneTree.build({ "terrain": value }); }) gui.add(option, 'tiles').name("3d瓦片").onChange(function (value) { sceneTree.build({ "_3dtiles": value }); }) gui.add(option, 'btnCut').name("截取场景"); $$('.dg.ac').css('top', '10%'); 场景树封装:SceneTree 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327/** * @file sceneTree * @version 1.0 * sceneTree 类 * 在3d地球上挂载场景 * * */import {CesiumTerrainProvider,EllipsoidTerrainProvider,GridImageryProvider,KmlDataSource,JulianDate,ClockRange,ClockStep,GeoJsonDataSource, Cartesian3} from 'cesium'import Rain from './libs/rain';import Snow from './libs/snow';let _self;export default class sceneTree { constructor(core) { /** * root 节点 */ this.root = null; /** * viewer */ this.viewer = core; /** * 场景 */ this.S = core.scene; //辅助对象 _self = this; /** * 状态码 */ this.STATUS = { CREATE: "No", CLOSE: "Off" } } /** * build 接口 */ build(trees) { if (trees == undefined) { alert("没有获取到功能节点"); } let _self = this; //自转 if (trees.rotation != undefined) { if (trees.rotation) { this.rotation({ cmd: "No" }); } else { this.rotation({ cmd: "Off" }); } } //雾天 if (trees.fog != undefined) { this.S.fog.enabled = trees.fog; } //昼夜 if (trees.lighting != undefined) { this.S.globe.enableLighting = trees.lighting; } //大气层 if (trees.groundAtmosphere != undefined) { this.S.globe.showGroundAtmosphere = trees.groundAtmosphere; } //地球 if (trees.globe != undefined) { this.S.globe.show = trees.globe; } //星空 if (trees.skyBox != undefined) { this.S.skyBox.show = true; } //太阳 if (trees.sun != undefined) { this.S.sun.show = trees.sun; } //雨天 if (trees.rain != undefined) { if (trees.rain) { setTimeout(()=> { this._rain = new Rain(this.viewer); }, 100) } else { this._rain.remove(); } } //雪天 if (trees.snow != undefined) { if (trees.snow) { setTimeout( ()=> { this._snow= new Snow(this.viewer); }, 100) } else { this._snow.remove(); } } //经纬网 if (trees.grid != undefined) { if (1 == trees.grid.cmd) { if (trees.grid.flag) { this.scene.grid({ cmd: "No" }); } else { this.scene.grid({ cmd: "Off" }); } } if (2 == trees.grid.cmd) { if (trees.grid.flag) { this.scene.tileGrid({ cmd: "No" }); } else { this.scene.tileGrid({ cmd: "Off" }); } } if (3 == trees.grid.cmd) { if (trees.grid.flag) { this.scene.mgrsGrid({ cmd: "No" }); } else { this.scene.mgrsGrid({ cmd: "Off" }); } } } //十字 if (trees.sbstyle != undefined) { if (trees.sbstyle) { document.documentElement.style.cursor = 'crosshair'; } else { document.documentElement.style.cursor = 'default'; } } //相机状态 if (trees.xjzt != undefined) { if (trees.xjzt) { $$('.map-move-msg').show(); } else { $$('.map-move-msg').hide(); } } //cesiumTool if (trees.cesiumTool != undefined) { if (trees.cesiumTool) { $$('.cesium-viewer-toolbar').show(); } else { $$('.cesium-viewer-toolbar').hide(); } } //时间轴 if (trees.sjz != undefined) { if (trees.sjz) { this.showTime(); } else { this.hideTime(); } } //信息框 if (trees.info != undefined) { if (trees.info) { $$('.cesium-infoBox').show(); } else { $$('.cesium-infoBox').hide(); } } //导航 if (trees.navi != undefined) { if (trees.navi) { $$('.cesium-widget-cesiumNavigationContainer').show(); } else { $$('.cesium-widget-cesiumNavigationContainer').hide(); } } //雷达 if (trees.radar != undefined) { if (trees.radar) { this.radar = new Radar({ viewer: this.viewer }); this.radar.build(4) } else { if (!this.radar) return; this.radar.dmRadar.remove(); } } //省份数据 if (trees.province != undefined) { if (trees.province) { this.createProvincesBorder(); } else { this.closeProvincesBorder(); } } //3dtile if (trees._3dtiles != undefined) { if (trees._3dtiles) { this.primitive.create3DTileset({ url: config.DATADIR + '/3DTiles/building/tileset.json' }); } else { this.primitive.remove3DTileset(); } } //地形 if (trees.terrain != undefined) { if (trees.terrain) { try { //this.viewer.scene.terrainProvider = createArcGisElevation3DTerrainProvider(Cesium); this.viewer.scene.terrainProvider = new CesiumTerrainProvider({ url: "/chinadem/" }) } catch (error) { alert("默认地形图加载异常"); } } else { this.viewer.scene.terrainProvider = new EllipsoidTerrainProvider({}); } } } /** * -------- * 辅助方法 * -------- */ /** * 地球自转 */ rotate() { let a = .1; let t = Date.now(); let n = (t - _self._rota) / 1e3; _self._rota = t; _self.S.camera.rotate(Cartesian3.UNIT_Z, -a * n); } rotation(opt) { if (opt.cmd == _self.STATUS.CREATE) { _self._rota = Date.now(); _self.CoreV.clock.onTick.addEventListener(_self.rotate); } if (opt.cmd == _self.STATUS.CLOSE) { _self.CoreV.clock.onTick.removeEventListener(_self.rotate); } } /** * 经纬网 */ grid(opt) { let _self = this; if (opt.cmd == _self.STATUS.CREATE) { let mapGrid = new GridImageryProvider(); _self.layerGrid = _self.imageryLayers.addImageryProvider(mapGrid);//添加注记图层 //_self.imageryLayers.grid.data = layer; _self.imageryLayers.raiseToTop(_self.layerGrid); //将注记图层置顶 } if (opt.cmd == _self.STATUS.CLOSE) { _self.imageryLayers.remove(_self.layerGrid); } //return _self.layer; } /** * 经纬网2 */ tileGrid(opt) { let _self = this; if (opt.cmd == _self.STATUS.CREATE) { let mapGrid = new TileLonlatsImageryProvider(); _self.layerTileGrid = _self.imageryLayers.addImageryProvider(mapGrid);//添加注记图层 //_self.imageryLayers.grid.data = layer; _self.imageryLayers.raiseToTop(_self.layerTileGrid); //将注记图层置顶 } if (opt.cmd == _self.STATUS.CLOSE) { _self.imageryLayers.remove(_self.layerTileGrid); } // return _self.layer; } /** * 军事网格 */ mgrsGrid(opt) { let _self = this; if (opt.cmd == _self.STATUS.CREATE) { var options = { camera: this.S.camera, canvas: this.S.canvas }; let pn = KmlDataSource.load("data/EarthPointGrid_093357.kml", options); pn.then(function (dataSource) { _self.xmlData = dataSource; _self.CoreV.dataSources.add(_self.xmlData); }); } if (opt.cmd == _self.STATUS.CLOSE) { _self.CoreV.dataSources.remove(_self.xmlData); } //return _self.xmlData; } /** * 日照分析 */ //显示动画时间轴 showTime() { if ($$('.map-move-msg').css('display') == 'none') { $$('.cesium-viewer-animationContainer').css('bottom', 0 + 'px'); $$('.cesium-viewer-timelineContainer').css('bottom', 0 + 'px'); } else { $$('.cesium-viewer-animationContainer').css('bottom', $$('.map-move-msg').height() + 'px'); $$('.cesium-viewer-timelineContainer').css('bottom', $$('.map-move-msg').height() + 'px'); } $$('.cesium-viewer-animationContainer').show(); $$('.cesium-viewer-timelineContainer').show(); } //隐藏动画时间轴 hideTime() { $$('.cesium-viewer-animationContainer').hide(); $$('.cesium-viewer-timelineContainer').hide(); } //省份数据 createProvincesBorder() { let _self = this; var promise = _self.viewer.dataSources.add(GeoJsonDataSource.load(config.DATADIR + '/china.json')); promise.then(function (dataSource) { _self.provinceData = dataSource; }).otherwise(function (error) { return new Errors(error); }); } //清除数据 closeProvincesBorder() { this.viewer.dataSources.remove(this.provinceData); }}","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"cesium|模拟扫描物实体功能","date":"2020-04-07T07:49:00.000Z","path":"2020/04/07/cesium-模拟扫描物实体功能/","text":"示例无人扫描示例 卫星过境示例 实现思路1.绘制圆柱体根据参数调成圆锥形状 2.加载动画czml路径 3.通过时钟对象获取当前路径点 4.将当前路径点通过 CallbackProperty 赋值给圆锥 5.路径点每次改动圆锥随之移动 代码获取路径点(移动的实体目标) 12345let cartesian = entity.position.getValue(this.clock.currentTime);let positions = this.mouseManager.worldToLonlat(cartesian); this.scanEntity = this.dynamicCylinder({positions:positions,entity:entityObj,v:this.CoreV,cylinder:{legnth:600000,slices:4,bottomRadius:600000/2}});this.EntityObj.push(this.entitys.add( this.scanEntity)); 传递的动态路径点 实现绑定效果(CallbackProperty) 1234567891011121314151617181920212223242526272829303132dynamicCylinder(obj) { let c = obj.cylinder; this.options = { cylinder: { HeightReference: HeightReference.RELATIVE_TO_GROUND, //表示相对于地形的位置。 length: c.length, //长度 topRadius: 0, //顶点半径 bottomRadius: c.bottomRadius, //底部半径 material: new Color(0, 1, 1, .4), slices: c.slices } } this.positions = obj.positions; this.entity = obj.entity; this.v = obj.v; var _self = this; var _update = function () { var positions = _self.entity.position.getValue(_self.v.clock.currentTime); var cartographic = _self.v.scene.globe.ellipsoid.cartesianToCartographic(positions); var lat = Math.toDegrees(cartographic.latitude) , lng = Math.toDegrees(cartographic.longitude) , hei = parseFloat(cartographic.height / 4); return Cartesian3.fromDegrees(lng, lat, 0); }; var _length = function () { var positions = _self.entity.position.getValue(_self.v.clock.currentTime); var cartographic = _self.v.scene.globe.ellipsoid.cartesianToCartographic(positions); return cartographic.height * 2; } this.options.position = new CallbackProperty(_update, false); this.options.cylinder.length = new CallbackProperty(_length, false); }","tags":[{"name":"Cesium","slug":"Cesium","permalink":"http://yoursite.com/tags/Cesium/"}]},{"title":"node|封装功能模块发布npm包","date":"2020-04-07T07:10:00.000Z","path":"2020/04/07/node-封装功能模块发布npm包/","text":"npmnpm是一个辅助前端开发的包管理工具 12345678910包括: 网站:找包、注册用户 命令行:程序员与npm交互的主要形式 仓库:最大的JavaScript软件库 管理对象:包(package) 管理方式: 增(发布:npm publish;安装:npm i) 删(废弃:npm deprecate;卸载:npm rm) 改(更新:npm up) 查(搜索:npm s) npm中涉及到的主体主要有两个:package和module,定义如下: package:含有package.json描述文件并发布到npm仓库的文件或者文件夹module:在node_modules中,可以被Node.js的require()方法加载的任何文件或文件夹可以这样理解:一个JavaScript软件,从本地发布到npm仓库时是package,从npm仓库下载到本地时就变成了module 另外,基于以上,可以看出package和module的关系: module不一定是package(比如node内置模块),package一定是module含package.json文件的module一定是package; 封装模块发布封装 注册一个npm账号 https://docs.npmjs.com/cli/publish.html 其中用户名会在发布npm包 初始化时用到 创建一个node项目并初始化 npm init依次输入信息 name 和 npm的username及password 初始化完成目录结构 准备好封装的工程文件 将功能模块集成到统一的入口文件中 测试通过… 发布npm包进入项目根目录 执行命令: npm version patch 每次发布前执行一下,避免版本冲突错误 npm publish 发布版本 查看发布的npm包 发布成功! 调用在第三方项目中需要使用该包 执行 npm install xxmap 根据npm 的 name安装 在工程中直接调用 启动并查看效果","tags":[{"name":"Node","slug":"Node","permalink":"http://yoursite.com/tags/Node/"}]},{"title":"ol-cesium|疫情可视化示例","date":"2020-04-06T09:26:00.000Z","path":"2020/04/06/ol-cesium-疫情可视化示例/","text":"前言最近在github上看到ol-cesium的开源库 在ol上集成cesium支持二三维联动。目前只是简单的切换联动,存在比较多的问题。init时候同时创建23d 对性能消耗比较大。 基于丁香园的数据做了一个简单的示例 ,用的框架和都是github现成的。 效果 功能比较简单,数据接口需要替换一下 数据爬虫接口本地部署的 1https://blog.csdn.net/weixin_40902527/article/details/104366065 github地址:地址","tags":[{"name":"ol-cesium","slug":"ol-cesium","permalink":"http://yoursite.com/tags/ol-cesium/"}]},{"title":"ol| 基于ol+es6+webpack的开发模版","date":"2020-04-06T09:20:00.000Z","path":"2020/04/06/ol-基于ol-es6-node-webpack的开发模版/","text":"前言将之前做的业务功能整合了一下, 拆分成几个常用模块进行业务封装,使每个模块提供一个接口达到快速开发的目的。集成了多个开源插件和UI,还在完善中... 效果支持地图基本服务和封装部分业务功能 封装常用控件及功能 一套完整的sdk工具 封装常用业务模块,提供接口服务 集成标绘 风场 图表等插件 还在完善中…","tags":[{"name":"openlayers","slug":"openlayers","permalink":"http://yoursite.com/tags/openlayers/"}]},{"title":"Es6 | 异步,导出导入,编译es5详解","date":"2020-04-06T09:11:00.000Z","path":"2020/04/06/Es6-导入导出和编译es5/","text":"ES6ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版。 ES6 主要是为了解决 ES5 的先天不足,比如 JavaScript 里并没有类的概念,但是目前浏览器的 JavaScript 是 ES5 版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功能。 async和await这里讲一下async和await虽然是es7新出的但是用的比较多。关于异步处理,ES5的回调使我们陷入地狱,ES6的Promise使我们脱离魔障,终于、ES7的async-await带我们走向光明。现在就看一下async-await 基本语法 123456async function basicDemo() { let result = await Math.random(); console.log(result);}basicDemo(); asyncasync用来表示函数是异步的,定义的函数会返回一个promise对象,可以使用then方法添加回调函数。 12345678async function demo01() { return 123;}demo01().then(val => { console.log(val);// 123});若 async 定义的函数有返回值,return 123;相当于Promise.resolve(123),没有声明式的 return则相当于执行了Promise.resolve(); awaitawait 可以理解为是 async wait 的简写。await 必须出现在 async 函数内部,不能单独使用。 1234function notAsyncFunc() { await Math.random();}notAsyncFunc(); await 后面可以跟任何的JS 表达式。虽然说 await 可以等很多类型的东西,但是它最主要的意图是用来等待 Promise 对象的状态被 resolved。如果await的是 promise对象会造成异步函数停止执行并且等待 promise 的解决,如果等的是正常的表达式则立即执行 1234567891011121314151617181920function sleep(second) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(' enough sleep~'); }, second); })}function normalFunc() { console.log('normalFunc');}async function awaitDemo() { await normalFunc(); console.log('something, ~~'); let result = await sleep(2000); console.log(result);// 两秒之后会被打印出来}awaitDemo();// normalFunc// VM4036:13 something, ~~// VM4036:15 enough sleep~ export在es6中一个文件可以默认为一个模块,模块通过export向外暴露接口,实现模块间交互等功能 相关语法 1234567891011121314151617181920212223242526export var m = 1;// 等价于var m = 1;export { m } // 导出多个var a = 1;var b = 2;var c = 3;export { a, b, c }// 导出对象export const student = { name: 'Megan', age: 18}// 导出函数export function add(a, b) { return a + b;}//导出接口别名const person = { name: '张呆', age: 18, gender: "male"}export { person as boy } export default 12345678910111213141516171819202122232425262728293031323334353637383940export default var i = 0;export导出语法 // default exportsexport default 42;export default {};export default [];export default foo;export default function () {}export default class {}export default function foo () {}export default class foo {} // variables exportsexport var foo = 1;export var foo = function () {};export var bar; // lazy initializationexport let foo = 2;export let bar; // lazy initializationexport const foo = 3;export function foo () {}export class foo {} // named exportsexport {foo};export {foo, bar};export {foo as bar};export {foo as default};export {foo as default, bar}; // exports fromexport * from "foo";export {foo} from "foo";export {foo, bar} from "foo";export {foo as bar} from "foo";export {foo as default} from "foo";export {foo as default, bar} from "foo";export {default} from "foo";export {default as foo} from "foo"; import12345678910111213141516171819import导入语法 // default importsimport foo from "foo";import {default as foo} from "foo"; // named importsimport {bar} from "foo";import {bar, baz} from "foo";import {bar as baz} from "foo";import {bar as baz, xyz} from "foo"; // glob importsimport * as foo from "foo"; // mixing importsimport foo, {baz as xyz} from "foo";import * as bar, {baz as xyz} from "foo";import foo, * as bar, {baz as xyz} from "foo"; 示例 123456789101112131415161718192021注意事项导入语句只能作为模块顶层的语句出现,不能出现在 function 里面或是 if 里面if(Math.random()>0.5){ import './module1.js'; // SyntaxError: Unexpected keyword 'import'}const import2 = (import './main2.js'); // SyntaxErrortry{ import './module3.js'; // SyntaxError: Unexpected keyword 'import'}catch(err){ console.error(err);}const moduleNumber = 4;import module4 from `module${moduleNumber}`; // SyntaxError: Unexpected token import 语句会被提升到文件顶部执行,也就是说在模块初始化的时候所有的 import 都必须已经导入完成import './module1.js';alert('code1');import module2 from './module2.js';alert('code2');import module3 from './module3.js'; babel初始化工程 npm init 配置.balbelrc文件添加 1234{ "presets": [], "plugins": []} 安装依赖 1234567891011# ES2015转码规则$ npm install --save-dev babel-preset-es2015 # react转码规则$ npm install --save-dev babel-preset-react # ES7不同阶段语法提案的转码规则(共有4个阶段),选装一个$ npm install --save-dev babel-preset-stage-0$ npm install --save-dev babel-preset-stage-1$ npm install --save-dev babel-preset-stage-2$ npm install --save-dev babel-preset-stage-3 将配置的规则加入.balbelrc 12345678{ "presets": [ "es2015", "react", "stage-2" ], "plugins": [] } 安装babel-cli工具 1npm install --save-dev babel-cli 转换 npm run build","tags":[{"name":"web","slug":"web","permalink":"http://yoursite.com/tags/web/"}]},{"title":"node|基于node的爬虫服务","date":"2020-04-06T09:03:00.000Z","path":"2020/04/06/node-基于node的云函数爬虫/","text":"前言爬取丁香园的数据并提供api,为界面可视化提供接口服务。 安装1234安装nodejs查看版本npm -v新建api项目 执行npm init 初始化package.json添加依赖包 执行npm install express body-parser mysql cors request --save 添加配置新建index.js 12345678910111213141516171819202122232425262728293031323334353637383940414243/* 引入express框架 */const express = require('express');const app = express(); /* 引入cors */const cors = require('cors');app.use(cors()); /* 引入body-parser */const bodyParser = require('body-parser');app.use(bodyParser.json());app.use(bodyParser.urlencoded({ extended: false })); /* 引入mysql const mysql = require('mysql');const conn = mysql.createConnection({ host: 'localhost', user: 'root', password: '123456', database: 'test', multipleStatements: true})*/ const ncov = require('./getDxyData') /* 监听端口 */app.listen(8585, () => { console.log('——————————服务已启动——————————');}) app.get('/', (req, res) => { res.send('<p style="color:red">服务已启动</p>');}) app.get('/api/getNcovData', (req, res) => { ncov.main_handler((data)=>{ res.json(data) })}) 引入函数文件 getDxyData.js 爬取丁香园数据 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182const request = require('request')//获取丁香园疫情数据async function getDxyData() { try { const body = await new Promise( (resolve, reject) => { request({ method: 'GET', uri: 'https://ncov.dxy.cn/ncovh5/view/pneumonia' }, (error, response, body) => { if (error) return reject(error) resolve(body) }) } ) const statistics = JSON.parse(/getStatisticsService\\s*=\\s*(.*?)}catch/.exec(body)[1]) const timeline = JSON.parse(/getTimelineService\\s*=\\s*(.*?)}catch/.exec(body)[1]) const areaStatistics = JSON.parse(/getAreaStat\\s*=\\s*(.*?)}catch/.exec(body)[1]) let listByArea = areaStatistics.map((x) => { return { provinceName: x.provinceName, provinceShortName: x.provinceShortName, tags: x.tags, confirmed: x.confirmedCount, suspected: x.suspectedCount, cured: x.curedCount, dead: x.deadCount, comment: x.comment, cities: x.cities.map((x) => { return { cityName: x.cityName, confirmed: x.confirmedCount, suspected: x.suspectedCount, cured: x.curedCount, dead: x.deadCount } }) } }) let listByOther = JSON.parse(/getListByCountryTypeService1\\s*=\\s*(.*?)}catch/.exec(body)[1]) listByOther = listByOther.map((x) => { return { provinceId: x.provinceId, provinceName: x.provinceName, provinceShortName: x.provinceShortName, tags: x.tags, confirmed: x.confirmedCount, suspected: x.suspectedCount, cured: x.curedCount, dead: x.deadCount, comment: x.comment, createTime: x.createTime, modifyTime: x.modifyTime, } }) return { readme: { source: 'https://ncov.dxy.cn/ncovh5/view/pneumonia', statistics: '数据概要', listByArea: '国内数据', listByOther: '国外数据', timeline: '实时播报' }, statistics, listByArea, listByOther, timeline } } catch (err) { return null }} exports.main_handler = async (callback) => { const data = await getDxyData() if (!data)callback({ error: 1, message: '加载失败,刷新再试' }) callback({ error: 0, message: '数据获取成功',data:data }) } 执行命令 index.js ```12打开页面访问 : ```http://localhost:8585/api/getNcovData","tags":[{"name":"Node","slug":"Node","permalink":"http://yoursite.com/tags/Node/"}]},{"title":"python|机器学习之随机森林算法","date":"2020-04-06T08:41:00.000Z","path":"2020/04/06/python-机器学习之随机森林算法/","text":"前言随机森林Python版本有很可以调用的库,使用随机森林非常方便,主要用到以下的库 sklearnScikit learn 也简称 sklearn, 是机器学习领域当中最知名的 python 模块之一.Sklearn 包含了很多种机器学习的方式: Classification 分类 Regression 回归 Clustering 非监督分类 Dimensionalityreduction 数据降维 Model Selection 模型选择 Preprocessing 数据预处理 Sklearn快速入门:https://www.jianshu.com/p/cd5a929bec33 numpynumpy(Numerical Python)提供了python对多维数组对象的支持:ndarray,具有矢量运算能力,快速、节省空间。numpy支持高级大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。 numpy快速入门:https://blog.csdn.net/cxmscb/article/details/54583415 pandaspandas 是基于 Numpy 构建的含有更高级数据结构和工具的数据分析包 类似于 Numpy 的核心是 ndarray,pandas 也是围绕着 Series 和 DataFrame 两个核心数据结构展开的 。Series 和 DataFrame 分别对应于一维的序列和二维的表结构。 pandas使用教程:https://blog.csdn.net/qq_38251616/article/details/79775789 RandomForestRegressor 导入模块,创建模型 1234import matplotlib.pyplot as plt #可视化图形库import numpy as np #numpy多维数值操作库import pandas as pd #pandas数据分析库from sklearn import datasets, cross_validation, ensemble #sklearn机器学习库 引入数据,对数据进行分集 1234567'''加载用于回归问题的数据集 :return: 一个元组,用于回归问题。元组元素依次为:训练样本集、测试样本集、训练样本集对应的值、测试样本集对应的值 ''' diabetes = datasets.load_diabetes() # 使用 scikit-learn 自带的一个糖尿病病人的数据集 return cross_validation.train_test_split(diabetes.data, diabetes.target, test_size=0.25, random_state=0) # 拆分成训练集和测试集,测试集大小为原始数据集大小的 1/4 模型预测 12345678910''' 测试 RandomForestRegressor 的用法 :param data: 可变参数。它是一个元组,这里要求其元素依次为:训练样本集、测试样本集、训练样本的 值、测试样本的值 :return: None ''' X_train, X_test, y_train, y_test = data regr = ensemble.RandomForestRegressor() regr.fit(X_train, y_train) print("Traing Score:%f" % regr.score(X_train, y_train)) print("Testing Score:%f" % regr.score(X_test, y_test)) 训练集:0.89 测试集 :0.24 自定义模型123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201# -*- coding: UTF-8 -*-import pandas as pdimport numpy as npfrom sklearn.ensemble import RandomForestRegressorfrom sklearn.cross_validation import train_test_splitfrom sklearn.decomposition import PCAfrom sklearn import preprocessingfrom sklearn.externals import joblib# 各指数计算# PCA降维def pcachange(pcadata): global MType pcadata1 = pcadata.fillna(0) pca = PCA(n_components=1) data_new = pca.fit_transform(pcadata1) print pcadata1.columns, pca.explained_variance_ratio_ joblib.dump(pca, unicode('D:/pca/' + str(MType) + '.m', 'utf-8')) minmax_scaler = preprocessing.MinMaxScaler(feature_range=(0, 100)) joblib.dump(pca, unicode('D:/minmax/' + str(MType) + '.m', 'utf-8')) data_minmax = minmax_scaler.fit_transform(data_new) return data_minmax #分组计算def cal_zs(input_features): for col in input_features: 'print(data[col])' data_output = data[col] data_output1 = pcachange(data_output) data_output2 = pd.DataFrame(data_output1) return data_output2 #整个预处理过程def preprocess(data_raw): global MType MType = 0 info = data_raw.iloc[:,0:12] #diannei = data_raw.iloc[:,22:89] ylsale =data_raw.iloc[:,-2] sale =data_raw.iloc[:,-1] ls_features = [['t130403','t130201','t130200','t130204','t130207','t130102','t130103','t130105','t130106','t130104','t130101']] xzl_features = [['t200103','t200104']] yl_features = [['t180201','t180400','t180402','t180403','t180209','t180205','t180202','t180210','t180203', 't180103','t180106','t180105','t180104','t180110','t180107','t180102','t180111','t180101','t180100','t120201','t120202','t120101','t120102']] cy_features = [['t110101','t110102','t110103','t110200','t110301','t110303','t110302']] fw_features = [['t230224','t230212','t230206','t230213','t230230','t230223','t230129','t230112','t230125','t230107','t230126','t230100','t230103','t230108']] jy_features = [[ 't160103', 't160104', 't160105']] jj_features = [ ['t800000', 't800001', 't800010', 't800011', 't800012', 't800013', 't800014', 't800020', 't800030', 't800031', 't800032', 't800035', 't800036', 't800037', 't8_0_19', 't8_0_29', 't8_0_39', 't8_0_49', 't8_10_29', 't8_10_39', 't8_10_49', 't8_20_39', 't8_20_49', 't8_30_49']] MType = MType + 1 lszs = cal_zs(ls_features) MType = MType + 1 xzlzs = cal_zs(xzl_features) MType = MType + 1 ylzs = cal_zs(yl_features) MType = MType + 1 cyzs = cal_zs(cy_features) MType = MType + 1 fwzs = cal_zs(fw_features) MType = MType + 1 jyzs = cal_zs(jy_features) MType = MType + 1 jjzs = cal_zs(jj_features) lszs.columns = ['lszs'] xzlzs.columns = ['xzlzs'] ylzs.columns = ['ylzs'] cyzs.columns = ['cyzs'] jyzs.columns = ['jyzs'] jjzs.columns = ['jjzs'] ls = data_raw[['t130403','t130201','t130200','t130204','t130207','t130102','t130103','t130105','t130106','t130104','t130101']] cy = data_raw[['t110101','t110102','t110103','t110200','t110301','t110303','t110302']] fw = data_raw[['t230224','t230212','t230206','t230213','t230230','t230223','t230129','t230112','t230125','t230107','t230126','t230100','t230103','t230108']] yl = data_raw[['t180201', 't180400', 't180402', 't180403', 't180209', 't180205', 't180202', 't180210', 't180203', 't180103', 't180106', 't180105', 't180104', 't180110', 't180107', 't180102', 't180111', 't180101', 't180100', 't120201', 't120202', 't120101', 't120102']] jj = data_raw[['t800000', 't800001', 't800010', 't800011', 't800012', 't800013', 't800014', 't800020', 't800030', 't800031', 't800032','t800035','t800036', 't800037', 't8_0_19', 't8_0_29', 't8_0_39', 't8_0_49', 't8_10_29', 't8_10_39', 't8_10_49', 't8_20_39', 't8_20_49', 't8_30_49']] data_pre = pd.concat([info,lszs,xzlzs,ylzs,jyzs,ls,cy,cyzs,fw,fwzs,jjzs,jj,yl,ylsale,sale],axis = 1) return data_pre filepath = u'D:/data/f1.csv'labelpath = u'D:/data/f2.csv'data = pd.read_csv(filepath, header=0, sep=',',na_values='NULL')label = pd.read_csv(labelpath, header=0, sep=',') data2 = preprocess(data)x_labels = data2.columns[12:-2]x_labels_t = np.array(x_labels).Tprint x_labels # 销量分等级def cat_sale(inputdata): y1 = inputdata.iloc[:, -1] # 销量 inputdata['salecat'] = pd.qcut(y1, 10, labels=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) inputdata['salecat'] = inputdata['salecat'].astype(int) return inputdata # 随机森林算法def rt_method(x_train, y_train, x_test, y_test): global CityIndex,CityName x_train1 = x_train.iloc[:, 12:] info_train = x_train.iloc[:, 0:12] info_train1 = info_train.reset_index(drop=True) rf0 = RandomForestRegressor(n_estimators=100, max_features='sqrt',oob_score=True) x_test1 = x_test.iloc[:, 12:] #rf0.fit(x_test1, y_test) rf0.fit(x_train1, y_train) y1 = rf0.predict(x_train1) y_train_pred = pd.DataFrame(y1, columns=['cat_pred']) y_train1 = y_train.reset_index(drop=True) info_test = x_test.iloc[:, 0:12] info_test1 = info_test.reset_index(drop=True) y2 = rf0.predict(x_test1) y_test_pred = pd.DataFrame(y2, columns=['cat_pred']) y_test1 = y_test.reset_index(drop=True) result_train = pd.concat([info_train1, y_train_pred, y_train1], axis=1) result_train1 = result_train.rename(columns={'salecat': 'cat_true'}) result_train1['PCV'] = result_train1['cat_pred'] * 10 result_train1.to_csv(unicode('D:/train.csv','utf-8'), index=False, sep=',') result_test = pd.concat([info_test1, y_test_pred, y_test1], axis=1) result_test1 = result_test.rename(columns={'salecat': 'cat_true'}) result_test1['PCV'] = result_test1['cat_pred'] * 10 result_test1.to_csv(unicode('D:/test.csv','utf-8'), index=False, sep=',') r1 = result_train1.cat_pred.corr(result_train1.cat_true) r2 = result_test1.cat_pred.corr(result_test1.cat_true) print r1, r2 result.loc[CityIndex, ['train_R']] = r1 result.loc[CityIndex, ['test_R']] = r2 importances = rf0.feature_importances_ df_ipt = pd.DataFrame(importances, columns=["feature_importance"]) feature_imp["feature_importance"] = df_ipt return rf0 global CityName,CityIndexCityIndex = 0feature_imp = pd.DataFrame(data=[])feature_imp['feature'] = x_labels_tresult = pd.DataFrame(data=[], index=[], columns=['city', 'train_R', 'test_R', 'num'])data3 = cat_sale(data)X = data3.iloc[:, 0:-2]Y = data3['salecat']Y = Y.fillna(1)X1 = X.fillna(0) # 用0填充空值X2 = X1.replace('t', 1) # 用1填充t值X_train, X_test, Y_train, Y_test = train_test_split(X2, Y, test_size=0.3, random_state=42)rf = rt_method(X_train, Y_train, X_test, Y_test)joblib.dump(rf, unicode('D:/data/model/0116/ly/全国.m', 'utf-8')) '''for city, ctdata in data3.groupby(['city_name']): print city, CityIndex CityName = city result.loc[CityIndex, ['city']] = city n = ctdata.iloc[:, 0].size # 行数 if n > 20: X = ctdata.iloc[:, 0:-2] Y = ctdata['salecat'] Y = Y.fillna(1) X1 = X.fillna(0) # 用0填充空值 X2 = X1.replace('t', 1) # 用1填充t值 X_train, X_test, Y_train, Y_test = train_test_split(X2, Y, test_size=0.3, random_state=42) try: rf = rt_method(X_train, Y_train, X_test, Y_test) joblib.dump(rf, unicode('D:/data/model/0115/ly/' + str(CityName) + '.m', 'utf-8')) except: print ('wrong') else: print n result.loc[CityIndex, ['num']] = n CityIndex = CityIndex + 1''' feature_imp1 = pd.merge(label, feature_imp, on='feature',how = 'right') result.to_csv(u'D:/R.csv', index=False, sep=',',encoding = 'gbk')feature_imp1.to_csv(u'D:/变量重要性.csv', index=False, sep=',',encoding = 'gbk')","tags":[{"name":"Python","slug":"Python","permalink":"http://yoursite.com/tags/Python/"}]},{"title":"mysql|关联表字段同步","date":"2020-04-06T08:30:00.000Z","path":"2020/04/06/mysql-两张表关联字段同步字段内容/","text":"数据表表1 表2 同步把一张表中的某个字段内容同步到另一张表的字段,前提条件是两张表要有关联字段方式1: 123456update table_name1 aset a.name= (select b.name from table_name2 b where a.oid= b.id)where exists (select 1 from table_name2 c where a.oid= c.id); exists用于检查子查询是否至少会返回一行数据(即exists 指定一个子查询,检测行的存在);该子查询实际上并不返回任何数据,而是返回值True或False 方式2: 12345678910111213141516171819UPDATE table_name1 pLEFT JOIN table_name2 aON p.oid= a.idSET a.name = p.nameWHERE p.name != '' #############UPDATE A LEFT OUTER JOIN B ON A.ID = B.IDLEFT OUTER JOIN C ON A.ID = C.IDSET A.NAME = C.NAME, A.TYPE = B.TYPEWHERE A.ID = #{ID} AND A.S_ID = #{S_ID}AND A.P_ID = #{P_ID};","tags":[{"name":"Mysql","slug":"Mysql","permalink":"http://yoursite.com/tags/Mysql/"}]},{"title":"linux|CentOS6.5升级GCC","date":"2020-04-06T08:27:00.000Z","path":"2020/04/06/linux-CentOS6-5升级GCC/","text":"前言CentOS 6.5 系统自带GCC版本4.4.7 太老 在编译源码的时候经常报错unrecognized command line option “-std=c++11” 升级GCC版本安装gcc需要先安装依赖包 gmp, mpfr, mpc 安装 gmp1234567wget http://mirror.hust.edu.cn/gnu/gmp/gmp-6.1.0.tar.xztar zxf gmp-6.1.0.tar.xzcd gmp-6.1.0./configure --prefix=/usr/local/gmp#成功会出现configure.status文件makemake install 安装mpfr1234567wget http://mirror.hust.edu.cn/gnu/mpfr/mpfr-3.1.4.tar.gztar zxf mpfr-3.1.4.tar.gzcd mpfr-3.1.4./configure --prefix=/usr/local/mpfx#成功会出现configure.status文件makemake install 安装 mpc1234567wget http://mirror.hust.edu.cn/gnu/mpc/mpc-1.0.3.tar.gztar zxf mpc-1.0.3.tar.gzcd mpc-1.0.3./configure --prefix=/usr/local/mpc#成功会出现configure.status文件makemake install 下载安装gcc123456789101112wget http://mirror0.babylon.network/gcc/releases/gcc-4.8.5/gcc-4.8.5.tar.gztar zxvf gcc-4.8.5.tar.gzcd gcc-4.8.5./configure --help #查看帮助命令./configure --enable-checking=release --enable-languages=c,c++ --disable-multilibmake j4/j8 #编译时间较长 -jn n代表cpu数 加快编译速度make install升级gcc动态链接库,把gcc-build-6.1.0/stage1-x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.22拷贝到/usr/lib64/文件夹下,首先删除原来软连接:rm -rf libstdc++.so.6然后新建软连接,指向libstdc++.so.6.0.22:ln -s libstdc++.so.6.0.22 libstdc++.so.6运行 gcc -v 查看版本 如果还是老版本:4.4.7 12345mv /usr/bin/gcc /usr/bin/gcc447mv /usr/bin/g++ /usr/bin/g++447ln -s /usr/local/gcc/bin/gcc /usr/binln -s /usr/local/gcc/bin/g++ /usr/bingcc -v","tags":[{"name":"Gcc","slug":"Gcc","permalink":"http://yoursite.com/tags/Gcc/"}]},{"title":"linux| 源码安装PostGIS","date":"2020-04-06T08:15:00.000Z","path":"2020/04/06/linux-源码安装PostGIS/","text":"准备先安装postgresql 源码安装:csdn地址 安装检查环境123rpm -qa | grep gcc-c++---如果没安装参考postgresql源码安装配置环境#安装依赖包:geos,proj,gdal,json-c,libxml2 编译 geos12345678wget https://download.osgeo.org/geos/geos-3.7.0.tar.bz2 #提前下载打包tar -zxvf geos-3.7.0.tar.bz2cd geos-3.7.0./configure --help #查看帮助命令./configure --prefix=/usr/local/geos#成功有configure.status 文件makemake install 编译 proj1234567wget http://download.osgeo.org/proj/proj-5.2.0.tar.gz #提前下载打包tar -zxvf proj-5.2.0.tar.gz cd proj-5.2.0./configure --prefix=/usr/local/proj#成功有configure.status 文件makemake install 编译 gdal1234567wget https://download.osgeo.org/gdal/2.3.2/gdal-2.3.2.tar.gz #提前下载打包tar -zxvf gdal-2.3.2.tar.gzcd gdal-2.3.2./configure --prefix=/usr/local/gdal --with-pg=/usr/local/pgsql/bin/pg_config#成功有configure.status 文件makemake install 编译 json-c1234567wget https://github.com/json-c/json-c/archive/json-c-0.13.1-20180305.tar.gztar -zxvf json-c-0.13.1-20180305.tar.gzcd json-c-0.13.1-20180305./configure --prefix=/usr/local/json-c#成功有configure.status 文件makemake install 编译 libxml21234567wget https://github.com/GNOME/libxml2/archive/v2.9.7.tar.gz #提前下载打包tar -zxvf libxml2-sources-2.9.7.tar.gz cd libxml2-2.9.7./configure --prefix=/usr/local/libxml2#成功有configure.status 文件makemake install 安装PostGis配置环境1234567891011vi /etc/id.so.confinclude ld.so.conf.d/*.conf/usr/local/pgsql/lib/usr/local/proj/lib/usr/local/gdal/lib/usr/local/geos/lib/usr/local/json-c/lib/usr/local/libxml2/lib#保存ldconfig -v 下载postgis123456wget http://download.osgeo.org/postgis/source/postgis-2.5.0.tar.gz #提前下载tar -zxvf postgis-2.5.0.tar.gzcd postgis-2.5.0./configure --prefix=/usr/local/pgsql --with-gdalconfig=/usr/local/gdal/bin/gdal-config --with-pgconfig=/usr/local/pgsql/bin/pg_config --with-geosconfig=/usr/local/geos/bin/geos-config --with-projdir=/usr/local/proj--with-xml2config=/usr/local/libxml2/bin/xml2-config --with-jsondir=/usr/local/json-cmakemake install postgresql 数据库安装postgis扩展1234567su -postgrespassword:create database gis_demo;\\c gis_demo;create extension postgis;CREATE EXTENSION---成功 常见错误如果出现编译错误:libmpc.so.3: cannot open shared object file: No such file or directory 参考这篇文章:csdn地址","tags":[{"name":"postgresql","slug":"postgresql","permalink":"http://yoursite.com/tags/postgresql/"}]},{"title":"Postgresql|存储过程脚本","date":"2020-04-06T08:02:00.000Z","path":"2020/04/06/Postgresql-存储过程脚本/","text":"Postgresql函数PostgreSQL函数也称为PostgreSQL存储过程。 PostgreSQL函数或存储过程是存储在数据库服务器上并可以使用SQL界面调用的一组SQL和过程语句(声明,分配,循环,控制流程等)。 它有助于您执行通常在数据库中的单个函数中进行多次查询和往返操作的操作。可以在许多语言(如SQL,PL/pgSQL,C,Python等)中创建PostgreSQL函数 12345678910CREATE [OR REPLACE] FUNCTION function_name (arguments) RETURNS return_datatype AS $variable_name$ DECLARE declaration; [...] BEGIN < function_body > [...] RETURN { variable_name | value } END; LANGUAGE plpgsql; 参数说明function_name 指定函数的名称。 [OR REPLACE] 是可选的,它允许您修改/替换现有函数。 RETURN 它指定要从函数返回的数据类型。它可以是基础,复合或域类型,或者也可以引用表列的类型。 function_body function_body包含可执行部分。 plpgsql 它指定实现该函数的语言的名称。 示例 对数据进行检测并打标记 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778CREATE OR REPLACE FUNCTION \"public\".\"pg_materules\"(varchar) RETURNS \"pg_catalog\".\"int4\" AS $BODY$ Declare tableName VARCHAR; sql VARCHAR; res int; Begin tableName:=$1; res:=0; ---- 初始化表内容 sql = 'update '||tableName||' set err_message=''异常信息:'';';execute sql; ---- ----数据表字段检查 sql:= 'select count(*) from information_schema.columns WHERE table_name = '''||tableName||''' and column_name = ''id'';'; execute sql into res; if res is null or res=0 then sql = 'update '||tableName||' set err_message=err_message||''ID字段缺失,'';';execute sql; end if; sql:= 'select count(*) from information_schema.columns WHERE table_name = '''||tableName||''' and column_name = ''name'';'; execute sql into res; if res is null or res=0 then sql = 'update '||tableName||' set err_message=err_message||''NAME字段缺失,'';';execute sql; end if; sql:= 'select count(*) from information_schema.columns WHERE table_name = '''||tableName||''' and column_name = ''citycode'';'; execute sql into res; if res is null or res=0 then sql = 'update '||tableName||' set err_message=err_message||''CITYCODE字段缺失,'';';execute sql; end if; ---- ---- 坐标检查 ---- sql:= 'select count(*) from information_schema.columns WHERE table_name = '''||tableName||''' and column_name = ''lat'';'; execute sql into res; if res is null or res=0 then sql = 'update '||tableName||' set err_message=err_message||''LAT字段缺失,'';';execute sql; else ----初始化坐标类型 sql = 'ALTER TABLE '||tableName||' ALTER COLUMN lat TYPE varchar(100);';execute sql; sql:= 'update '||tableName||' set err_message=err_message||''缺失坐标LAT,'' where lat='''' or lat is null;';execute sql; end if; sql:= 'select count(*) from information_schema.columns WHERE table_name = '''||tableName||''' and column_name = ''lon'';'; execute sql into res; if res is null or res=0 then sql = 'update '||tableName||' set err_message=err_message||''LON字段缺失,'';';execute sql; else ----初始化坐标类型 sql = 'ALTER TABLE '||tableName||' ALTER COLUMN lon TYPE varchar(80);';execute sql; sql:= 'update '||tableName||' set err_message=err_message||''缺失坐标LON,'' where lon='''' or lon is null;';execute sql; end if; ---- ---- 销售额字段检查处理 ---- sql:= 'select count(*) from information_schema.columns WHERE table_name = '''||tableName||''' and column_name = ''sale'';'; execute sql into res; if res is null or res=0 then sql = 'update '||tableName||' set type_message=''空白门店'';';execute sql; else ----初始化销售额类型 sql = 'ALTER TABLE '||tableName||' ALTER COLUMN sale TYPE INT;';execute sql; sql = 'update '||tableName||' set type_message=''覆盖门店'' where type_message='''' or type_message is null;';execute sql; sql:= 'update '||tableName||' set err_message=err_message||''销售额异常,'' where sale is null or sale <=0;';execute sql; end if; ---- ---- 业态检查 ---- sql:= 'select count(*) from information_schema.columns WHERE table_name = '''||tableName||''' and column_name = ''yt'';'; execute sql into res; if res is null or res=0 then sql = 'update '||tableName||' set err_message=err_message||''YT字段缺失,'';';execute sql; else sql:= 'update '||tableName||' set err_message=err_message||''缺失业态,'' where yt = '''' or yt is null;';execute sql; end if; return 0; end; $BODY$ LANGUAGE plpgsql VOLATILE COST 100 给某张表添加多个列 1234567891011121314151617181920CREATE OR REPLACE FUNCTION \"public\".\"pg_addcolumn\"(_text, varchar) RETURNS \"pg_catalog\".\"int4\" AS $BODY$ Declare cols text[]; newTableName VARCHAR; scount INTEGER; sql VARCHAR; Begin cols:=$1; newTableName:=$2; scount:= array_length(cols,1); for i in 1..scount loop sql:='alter table '||newTableName||' add column '||quote_ident(cols[i])||' VARCHAR default null;'; EXECUTE sql; end LOOP; return 0; end; $BODY$ LANGUAGE plpgsql VOLATILE COST 100 删除三个月以前的数据 12345678910CREATE OR REPLACE FUNCTION delete_ebd_compute_log_three_month_ago_data() RETURNS void AS$BODY$ begin delete from ebd_compute_log where create_time < CURRENT_TIMESTAMP(0) :: TIMESTAMP WITHOUT TIME ZONE - interval '3 months'; END;$BODY$LANGUAGE plpgsql VOLATILE; GRANT EXECUTE ON FUNCTION delete_ebd_compute_log_three_month_ago_data() TO public;","tags":[{"name":"postgresql","slug":"postgresql","permalink":"http://yoursite.com/tags/postgresql/"}]},{"title":"python| socket聊天室","date":"2020-04-06T07:55:00.000Z","path":"2020/04/06/python-聊天室/","text":"服务端1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283import socketimport timeimport tkinterfrom tkinter.scrolledtext import ScrolledTextimport threadingimport requestsimport tkinterfrom socket import *from time import ctimefrom tkinter import * global Text_Show # 调用人工智能对话的函数,返回人工智能回答 def AI_Talk(s): print(s) response = requests.post("http://www.tuling123.com/openapi/api", data={ "key": "4105cb6db8c54f5db470b6c0ee42d24b", "info": s}) response = response.json() answer = response['text'] return answer # 线程二函数,用来进行对话 def Sever_Thread(sock, caddr): Text_Show.insert('end', "客户端@" + str(caddr[1]) + "已连接!\\n") while True: # 接收数据 data = str(sock.recv(1024).decode('UTF-8')) if data == "quit": Text_Show.insert('end', "客户端@" + str(caddr[1]) + "终止了对话\\n") Text_Show.see(tkinter.END) break else: Text_Show.insert('end', "来自客户端@" + str(caddr[1]) + "的消息为:" + data + '\\n') Text_Show.see(tkinter.END) # 发送数据 time.sleep(0.2) data = AI_Talk(data) # # data = '请输入发送至客户端的数据: 123123' #如果要手动输入的话就要设置好线程sleep时间不然还没有输入,就已经到其他线程了,就会发不出去。 sock.sendall(bytes(data, 'UTF-8')) sock.close() # 线程一函数,监听端口,一旦有客户端接入,开启线程二 def Sever_Accept(ss): while True: sock, caddr = ss.accept() Thread2 = threading.Thread(target=Sever_Thread, args=(sock, caddr)) Thread2.daemon = True # 线程守护 Thread2.start() # 服务器初始化def Sever_Init(): HOST = '' PORT = 4700 ADDR = (HOST, PORT) ss = socket(AF_INET, SOCK_STREAM, 0) ss.bind(ADDR) ss.listen(20) # 允许最大监听数 Thread1 = threading.Thread(target=Sever_Accept, args=(ss,)) Thread1.daemon = True # 线程守护 Thread1.start() # 主函数 if __name__ == "__main__": root = tkinter.Tk() root.title("聊天小程序服务器端 ") frame1 = Frame(root) frame1.pack() IP_Show_Label = Label(frame1, text="默认IP:127.0.0.1\\n默认端口为6000\\n无法更改!!!") IP_Show_Label.pack(side='left') frame2 = Frame(root) frame2.pack() Text_Show = ScrolledText(frame2, width=100, height=30) Text_Show.bind("<KeyPress>", lambda e: "break") Text_Show.pack(side="bottom", fill='both', expand=True) Sever_Init() root.mainloop() 客户端代码1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677import socketimport timeimport tkinterfrom tkinter.scrolledtext import ScrolledTextimport threadingimport requestsimport tkinterfrom socket import *from time import ctimefrom tkinter import * global cs, Text_Show, Send_Show # 发送按键的函数def Click_Send(): sendData = Send_Show.get() # 获取输入内容 if sendData == 'quit': Text_Show.insert(tkinter.END, "与服务器连接已断开" + "\\n") Text_Show.see(tkinter.END) cs.sendall(bytes(sendData, encoding="utf8")) cs.close() else: Text_Show.insert(tkinter.END, "客户端:" + sendData + "\\n") Text_Show.see(tkinter.END) cs.sendall(bytes(sendData, encoding="utf8")) Send_Show.delete(0, END) # 线程函数,循环接受客户端消息def Receive_Data(): while True: accept_data = str(cs.recv(1024), encoding="utf8") Text_Show.insert(tkinter.END, "服务器:" + accept_data + "\\n") Text_Show.see(tkinter.END) # 主函数if __name__ == "__main__": # 初始化GUI root = tkinter.Tk() root.title("聊天小程序客户端 ") # 顶部显示部分 frame1 = Frame(root) frame1.pack() IP_Show_Label = Label(frame1, text="本程序默认IP:127.0.0.1\\n默认端口为6000\\n无法更改!!!") IP_Show_Label.pack(side='left') # 中部聊天框显示部分 frame2 = Frame(root) frame2.pack() Text_Show = ScrolledText(frame2, width=70, height=15) Text_Show.bind("<KeyPress>", lambda e: "break") Text_Show.pack(side="bottom", fill='both', expand=True) # 底部消息发送部分 frame3 = Frame(root) frame3.pack() e3 = StringVar() Send_Show = Entry(frame3, textvariable=e3, width=60) buttontext2 = tkinter.StringVar() buttontext2.set('发送') button_Send = tkinter.Button(frame3, width=10, textvariable=buttontext2, command=Click_Send) Send_Show.pack(side="left") button_Send.pack(side="left") frame3.pack() # 初始化TCP协议 HOST = '127.0.0.1' PORT = 4700 BUFSIZ = 1024 ADDR = (HOST, PORT) cs = socket(AF_INET, SOCK_STREAM, 0) cs.connect(ADDR) thread = threading.Thread(target=Receive_Data) thread.start() root.mainloop() 效果","tags":[{"name":"Python","slug":"Python","permalink":"http://yoursite.com/tags/Python/"}]},{"title":"爬虫|基于redis搭建IP代理池","date":"2020-04-06T07:46:00.000Z","path":"2020/04/06/爬虫-基于redis搭建IP代理池/","text":"前言爬虫爬取网页数据时由于频繁访问会被锁定IP,返回错误响应码以及验证字母验证,可以动态使用ip代理解决。代理服务可以自己搭建,也可以购买收费的强力代理服务更靠谱。 基于redis的ip池示例: 搭建环境: 123456windows下载地址:https://github.com/MicrosoftArchive/redis/releases#下载zip解压即可启动redis:运行redis-server.exe Linux安装:sudo apt-get install redis-server启动redis:运行redis-server 安装启动: 部署本地ip爬虫 12345#下载源码git clone git@github.com:jhao104/proxy_pool.git或者直接到https://github.com/jhao104/proxy_pool 下载zip文件,解压出来 安装依赖: 12#进入项目目录执行pip命令 也可以手动安装pip install -r requirements.txt 配置项目: 12345678910111213141516171819202122232425262728# Config/setting.py 为项目配置文件 # 配置DB DATABASES = { "default": { "TYPE": "SSDB", # 如果使用SSDB或redis数据库,均配置为SSDB "HOST": "127.0.0.1", # db host "PORT": 6379, # db port redis默认6379 "NAME": "proxy", # 默认配置 "PASSWORD": "" # db password }} # 配置 ProxyGetterPROXY_GETTER = [ "freeProxyFirst", # 这里是启用的代理抓取函数名,可在ProxyGetter/getFreeProxy.py 扩展 "freeProxySecond", ....] # 配置 API服务 SERVER_API = { "HOST": "0.0.0.0", # 监听ip, 0.0.0.0 监听所有IP "PORT": 5010 # 监听端口}#上面配置启动后,代理池访问地址为 http://127.0.0.1:5010 启动项目: 12345678# 如果你的依赖已经安全完成并且具备运行条件,可以直接在Run下运行main.py# 到Run目录下:>>>python main.py # 如果运行成功你应该看到有4个main.py进程 # 你也可以分别运行他们,# 依次到Api下启动ProxyApi.py,Schedule下启动ProxyRefreshSchedule.py和ProxyValidSchedule.py即可. 启动查看抓取的ip:http://127.0.0.1:5010/get_all/ 项目提供内置API: 爬虫动态代理1234567891011121314151617181920212223def get_proxy(): #可以换成我的Api return requests.get("http://127.0.0.1:5010/get/").text def getURL(self, url, redirects=False, tries_num=6, sleep_time=0.5, time_out=1000, max_retry=6, ): #从ip池动态获取一个ip proxy = get_proxy() try: res = requests.Session() # res = requests.get(url,headers=self.randHeader(), allow_redirects=redirects, timeout=time_out) res = requests.get(url,headers=self.randHeader(), allow_redirects=redirects, timeout=time_out, proxies={"http": "http://{}".format(proxy), "https": "https://{}".format(proxy)}) res.raise_for_status() # 如果响应状态码不是 200,就主动抛出异常 except requests.RequestException as e: sleep_time_p = sleep_time_p + 10 time_out_p = time_out_p + 10 tries_num_p = tries_num_p - 1 # 设置重试次数,最大timeout 时间和 最长休眠时间 if tries_num_p > 0: time.sleep(sleep_time_p) print (self.getCurrentTime(), url, 'URL Connection Error: 第', max_retry - tries_num_p, u'次 Retry Connection', e) return self.getURL(url, 'False', tries_num_p, sleep_time_p, time_out_p, max_retry) return res","tags":[{"name":"Python","slug":"Python","permalink":"http://yoursite.com/tags/Python/"}]},{"title":"爬虫| 基于高德api接口抓取景区/小区边界数据","date":"2020-04-06T07:10:00.000Z","path":"2020/04/06/爬虫-基于高德api接口抓取景区-小区边界数据/","text":"爬虫网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。 Python爬虫Python,丰富的第三方库十分强大,简单几行代码便可实现你想要的功能,更重要的,Python也是数据挖掘和分析的好能手。这样爬取数据和分析数据一条龙的服务都用Python 工作流程123456789抓取HTML页面:HTTP请求的处理: urllib, urlib2, requests 处理器的请求可以模拟浏览器发送请求,获取服务器响应的文件解析服务器相应的内容:re, xpath, BeautifulSoup(bs4), jsonpath, pyquery等使用某种描述性语言来给我们需要提取的数据定义一个匹配规则,符合这个规则的数据就会被匹配采集动态HTML,验证码的处理通用动态页面采集: Selenium + PhantomJS:模拟真实浏览器加载JS验证码处理: Tesseract机器学习库,机器图像识别系统 爬虫框架(Scrapy)Scrapy框架 : 12345678特点: 高定制性,高性能(异步网络框架twisted)->数据下载快,提供了数据存储,数据下载,提取规则等组件 分布式策略: scrapy redis:在scarpy基础上添加了以redis数据库为核心的一套组件,主要在redis做请求指纹去重、请求分配、数据临时存储爬虫、反爬虫、反反爬虫之间的斗争: User-Agent, 代理, 验证码, 动态数据加载, 加密数据 爬取高德数据边界高德api接口地址:1234567https://lbs.amap.com/api/webservice/guide/api/search如果不是高德开发者可以申请为开发者第一步,申请”Web服务API”密钥(Key);第二步,拼接HTTP请求URL,第一步申请的Key需作为必填参数一同发送;第三步,接收HTTP请求返回的数据(JSON或XML格式),解析数据。如无特殊声明,接口的输入参数和输出数据编码全部统一为UTF-8。 爬取思路通过高德搜索接口得到附近小区搜索列表解析后获取到正确小区的id。其中city是城市代码,可以通过浏览器手工获取到。words是搜索的具体风景区名称。 1https://restapi.amap.com/v3/place/text?key=4b86820a7590de60e4f81f53e59ae17f&citylimit=true&output=json& key 为申请的密钥,申请详细步骤文档有说明keywords 查询的关键词,如景区/小区名称city 查询的目标城市 示例 : 1https://restapi.amap.com/v3/place/text?key=4b86820a7590de60e4f81f53e59ae17f&citylimit=true&output=json&keywords=中山陵景区&city=南京 返回结果为json字符串提取景区/小区的id:B0FFHVEECG 爬取方案方案1 :然后通过poiid调用另外一个接口查询该景区/小区 1https://ditu.amap.com/detail/get/detail?id=B0FFHVEECG 参数 id 填写上面获取到的 poiid=B0FFHVEECG 请求返回结果:将返回的结果转成json然后逐层提取出来 存入数据库或者csv文档 123456789101112def info(self, response): meta = response.meta data = json.loads(response.text) print(data) try: if data["status"] == "1": spec = data["data"]["spec"] border = spec["mining_shape"]["shape"] print("border ",border) AllCityDataSQL().UpdateXcJingDianiData((meta["id"]),border) except: print("查询错误~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + meta["url"]) 方案2: 通过poiid查找边界信息,红色部分可以替换成其他城市代码(身份证前6位)和景区id 接口地址:https://gaode.com/service/poiInfo?query_type=IDQ&pagesize=20&pagenum=1&qii=true&cluster_state=5&need_utd=true&utd_sceneid=1000&div=PC1000&addr_poi_merge=true&is_classify=true&zoom=11&id=B022F0071G&city=341003 请求返回结果: value字段 由一堆坐标组成的数值 123将返回的结果转成json ,然后逐层提取出来返回的value字段值还需修改一下,将_换成,才能使用存入数据库或者csv文档 常见问题高德的反扒机制: 123错误数据接口异常跳转第三方接口 推荐使用ip代理搭建一个ip池:博客 常用反反爬机制:csdn地址 PhantomJS + selenium 防反爬:csdn地址","tags":[{"name":"Python","slug":"Python","permalink":"http://yoursite.com/tags/Python/"}]},{"title":"Java|基于springBoot的开源分布式系统","date":"2020-04-06T06:43:00.000Z","path":"2020/04/06/基于springBoot的开源分布式系统/","text":"springBoot123Spring Boot是为了简化Spring应用的创建、运行、调试、部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置。使基于Spring的应用开发,只需要“run”就能创建一个独立的、生产级别的Spring应用。Spring Boot为Spring平台及第三方库提供开箱即用的设置(提供默认设置),这样我们就可以简单的开始。多数Spring Boot应用只需要很少的Spring配置。简单来说,它提供了一堆依赖打包,并已经按照使用习惯解决了依赖问题---习惯大于约定。 四大核心1234567SpringBoot的四大核心:自动配置:针对很对spring应用程序常见的应用功能,SpringBoot能自动提供相关配置起步依赖:起步依赖和普通依赖的区别在于我们不需要传入版本号,它会根据springboot的版本号来进行依赖,解决了我们的版本不兼容性。命令行界面:这是SpringBoot的可选特性,借此 你只需要代码就能完成完整的应用程序,无需传统项目构建。(一般用于轻量级开发和测试)Actuator:是SpringBoot的一个附加功能,可以帮助你在应用程序生产环境时监视和管理应用程序。0特别对于微服务管理十分有意义。自动配置:简单的说 就是你写好代码 开启自动配置之后 springboot 会去找所有你配置好的bean 进行初始化 和 注入 等等操作 优点12345678SpringBoot主要优点:帮助开发者快速搭建Spring框架,无需配置自动整合第三方框架。帮助开发者快速启动一个web容器,内嵌servlet容器,降低了对环境的要求,可以使用命令直接执行项目,应用可用jar包执行:java -jar。继承了原有的Spring框架的优秀基因。简化了Spring的使用过程,提高了开发效率。提供了starter POM,可以非常方便 的对包进行管理,极大程度的减少了jar hell 和dependency hell。运行中对应用状态的监控。 springBoot 入门示例 :csdn地址 iBase4j说明123456iBase4J是Java语言的分布式系统架构。 使用Spring整合开源框架。使用Maven对项目进行模块化管理,提高项目的易开发性、扩展性。系统包括4个子系统:系统管理Service、系统管理Web、业务Service、业务Web。系统管理:包括用户管理、权限管理、数据字典、系统参数管理等等。业务相关:您的业务开发。可以无限的扩展子系统,子系统之间使用Dubbo或MQ进行通信。 特点12345678910111. 数据库:Druid数据库连接池,监控数据库访问性能,统计SQL的执行性能。 数据库密码加密,加密方式请查看PropertiesUtil,decryptProperties属性配置需要解密的key。2. 持久层:mybatis持久化,使用MyBatis-Plus优化,减少sql开发量;aop切换数据库实现读写分离。Transtraction注解事务。3. MVC: 基于spring mvc注解,Rest风格Controller。Exception统一管理。4. 调度:Spring+quartz, 可以查询、修改周期、暂停、删除、新增、立即执行,查询执行记录等。5. 基于session的国际化提示信息,职责链模式的本地语言拦截器,Shiro登录、URL权限管理。会话管理,强制结束会话。6. 缓存和Session:注解redis缓存数据;shiro实现redis分布式session同步,重启服务会话不丢失。7. 多系统交互:Dubbo,ActiveMQ多系统交互,ftp/sftp/fastdafs发送文件到独立服务器,使文件服务分离。8. 前后端分离:没有权限的文件只用nginx代理即可。9. 日志:log4j2打印日志,业务日志和调试日志分开打印。同时基于时间和文件大小分割日志文件。10. QQ、微信、新浪微博第三方登录。11. 工具类:excel导入导出,汉字转拼音,身份证号码验证,数字转大写人民币,FTP/SFTP/fastDFS上传下载,发送邮件,redis缓存,加密等等。 Spring,SpringBoot,SpringMVC,Mybatis,mybatis-plus,motan/dubbo分布式,Redis缓存,Shiro权限管理,Spring-Session单点登录,Quartz分布式集群调度,Restful服务,QQ/微信登录,App token登录,微信/支付宝支付;日期转换、数据类型转换、序列化、汉字转拼音、身份证号码验证、数字转人民币、发送短信、发送邮件、加密解密、图片处理、excel导入导出、FTP/SFTP/fastDFS上传下载、二维码、XML读写、高精度计算、系统配置工具类等等 搭建GitHub地址:https://github.com/iBase4J/iBase4J-SpringBoot项目依赖:redis zookeeper actionmqredis安装:https://www.cnblogs.com/M-LittleBird/p/5902850.htmlzookeeper 安装:https://www.cnblogs.com/lsdb/p/7297731.htmlactiveMq 安装 :https://blog.csdn.net/mr_haixin/article/details/80418204 git clone 项目 1git clone https://github.com/iBase4J/iBase4J-SpringBoot.git 导入开发工具 idea 配置环境 :idea2019 jdk1.8 mysql8 导入sql文件 启动脚本 依次导入脚本 修改配置文件,配置本地环境 默认加密密码:buzhidao =,= 自定义生成密码 启动脚手架 12SysServiceApplication.java runSysWebApplication.java run Api地址访问:http://localhost:8088/swagger-ui.html#/ 访问项目还需要配置 nginx 1234567891011121314151617181920212223242526272829303132333435server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; # 静态页面目录 root D:\\workspace\\iBase4J\\iBase4J-UI\\iBase4J-UI-AngularJS; # 默认首页 index index.html; location = / { index login.html index.html index.htm; } # 用户浏览器端的缓存设置 location ~* \\.(css|js|jpg|jpeg|gif|png|swf|htm|html|json|xml|svg|woff|ttf|eot|map|ico|woff2|apk)$ { proxy_cache_valid 200 304 4h; expires 4h; } proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; location /app/ { # 动态页面,交给tomcat处理 proxy_pass http://127.0.0.1:8090; } location / { # 动态页面,交给tomcat处理 proxy_pass http://127.0.0.1:8088; } } 搭建成功访问 :http://localhost/admin/111111","tags":[{"name":"JAVA","slug":"JAVA","permalink":"http://yoursite.com/tags/JAVA/"}]},{"title":"Java|微服务搭建","date":"2020-04-06T03:08:00.000Z","path":"2020/04/06/微服务搭建/","text":"微服务微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底去掉耦合,每一个微服务提供单个业务功能,一个服务只做一件事。从技术角度讲就是一种小而独立的处理过程,类似与进程的概念,能够自行单独启动或销毁,可以拥有自己独立的数据库 微服务框架:spring -cloud1234567891011121314Spring Cloud是一个完整的微服务解决方案,它提供分布式情况下的各种解决方案合集。而Dubbo是一款高性能的Java RPC框架。Spring Cloud生态和Dubbo生态随着技术的发展,会逐渐的融合互补总体架构 Service Provider: 暴露服务的提供方。 Service Consumer:调用远程服务的服务消费方。 EureKa Server: 服务注册中心和服务发现中心基础组件: 服务治理: Spring Cloud Eureka 客户端负载均衡: Spring Cloud Ribbon 服务容错保护: Spring Cloud Hystrix 声明式服务调用: Spring Cloud Feign API 网关服务:Spring Cloud Zuul 分布式配置中心: Spring Cloud Config spring-cloud详解: csdn地址 基于meven的spring - cloud搭建环境: 1ide工具:idea jdk版本:1.8 数据库:mysql8 工程目录: 构建父工程 新建一个空工程: File -> New -> New Project 创建完成有弹出框 新建modules,点击 + 号,新建一个父工程,也就是一个父 module。然后我们选择 maven 工程,选择 jdk 版本和模板,模板也可以不选择,我这里就没有选择,自己搭建即可; 在pom文件中设置spring boot的parent 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869<?xml version=\"1.0\" encoding=\"UTF-8\"?><project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"> <modelVersion>4.0.0</modelVersion> <groupId>com.demo</groupId> <artifactId>microservice</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <spring-cloud.version>Edgware.SR1</spring-cloud.version> <spring-boot.version>1.5.10.RELEASE</spring-boot.version> <mysql.version>5.1.46</mysql.version> <mybatis.version>1.3.2</mybatis.version> <lombok.version>1.16.18</lombok.version> </properties> <dependencyManagement> <dependencies> <!-- 定义 spring cloud 版本 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- 定义 spring boot 版本 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- 定义 mysql 版本 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- 定义 mybatis 版本 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.version}</version> </dependency> <!-- 定义 lombok 版本 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project> 父工程配置完了,子模块可以直接通过 <parent> 标签引用父工程的依赖包 构建common模块(公共服务模块)创建microservice-common模块(公共模块)供其子模块调用 在父工程中添加common子模块,右键microservice - new - module 123456789101112131415161718192021222324252627282930312. 在pom中添加依赖包``` <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>microservice</artifactId> <groupId>com.demo</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../microservice/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microservice-common</artifactId> <packaging>jar</packaging> <!-- 当前Module需要用到的依赖,按自己需求添加,版本号在父类已经定义了,这里不需要再次定义 --> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project> 在scr/main/java/下创建实体类,添加公共实体类供其他服务调用 123456789101112131415161718192021222324252627282930313233343536373839package com.demo.springcloud.entity; import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import lombok.experimental.Accessors; /** * 订单实体 *@AllArgsConstructor 注解:表示生成带有所有属性的构造方法 *@NoArgsConstructor 注解:表示生成不带参数的构方法 *@Data 注解:表示生成get和set方法 */@AllArgsConstructor@NoArgsConstructor@Datapublic class TOrder { /** * 主键id */ private Long id; /** * 商品名称 */ private String name; /** * 商品价格 */ private Double price; /** * 所存的数据库名称 */ private String dbSource;} 将common打包成jar文件,点击maven 分别 clean和 install一下 12345678910111213141516171819202122232425262728### 创建provider模块(服务提供者)创建服务提供者模块microservice-provider,添加方式和microservice-common一样。服务提供模块,主要负责在表中查询出订单信息,然后将信息通过接口提供给调用方,所以在该模块中,我们需要整合一下 mybatis:1. 在pom文件中配置整合的依赖包```bash# 服务端口号server: port: 8001 # 数据库地址datasource: url: localhost:3306/demo spring: application: name: microservice-order # 对外暴露的服务名称 datasource: # 数据库配置 driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://${datasource.url}?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10 username: root password: root hikari: maximum-pool-size: 10 # 最大连接池数 max-lifetime: 1770000 配置application.yml 1234567891011121314151617181920# 服务端口号server: port: 8001 # 数据库地址datasource: url: localhost:3306/demo spring: application: name: microservice-order # 对外暴露的服务名称 datasource: # 数据库配置 driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://${datasource.url}?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10 username: root password: root hikari: maximum-pool-size: 10 # 最大连接池数 max-lifetime: 1770000 创建数据持久层接口 12345678910 public interface OrderMapper { @Select("select * from microservice where id = #{id}") TOrder findById(Long id); @Select("select * from microservice") List<TOrder> findAll(); } 创建业务层接口以及实现类 123456789101112131415161718192021222324//业务层接口public interface OrderService { TOrder findById(Long id); List<TOrder> findAll();} //接口实现类@Servicepublic class OrderServiceImpl implements OrderService { @Resource private OrderMapper orderMapper; public TOrder findById(Long id) { return orderMapper.findById(id); } public List<TOrder> findAll() { return orderMapper.findAll(); }} 创建服务控制层 1234567891011121314151617@RestController@RequestMapping(\"/provider/order\")public class OrderProviderController { @Resource private OrderService orderService; @GetMapping(\"/get/{id}\") public TOrder getOrder(@PathVariable Long id) { return orderService.findById(id); } @GetMapping(\"/get/list\") public List<TOrder> getAll() { return orderService.findAll(); }} 创建服务启动类 123456789@SpringBootApplication@MapperScan("com.itcodai.springcloud.dao")public class OrderProvider { public static void main(String[] args) { SpringApplication.run(OrderProvider.class, args); }} 数据结构 1服务提供者模块搭建完了可以启动测试,浏览器输入:localhost:8001/provider/order/get/list 创建consumer模块(订单消费者)新建子模块的方法和上面两个子模块一样,在命名的时候命名为 microservice-consumer 即可。 microservice-consumer 模块主要是用来调用 microservice-provider模块提供的订单信息,所以在 microservice-consumer 模块中我们不需要引入 mybatis 和 mysql 相关的依赖; 在pom文件配置依赖包 1234567891011121314151617181920212223242526272829303132333435<?xml version=\"1.0\" encoding=\"UTF-8\"?><project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"> <parent> <artifactId>microservice</artifactId> <groupId>com.demo</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../microservice/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microservice-consumer</artifactId> <packaging>jar</packaging> <!-- 当前Module需要用到的依赖,按自己需求添加,版本号在父类已经定义了,这里不需要再次定义 --> <dependencies> <!-- 引入自己定义的 microservice-common 通用包,可以使用common模块中的Order类 --> <dependency> <groupId>com.demo</groupId> <artifactId>microservice-common</artifactId> <version>${project.version}</version> </dependency> <!-- spring boot web 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies></project> 创建RestTmplate类。在微服务都是以 HTTP 接口的形式暴露自身服务的,因此在调用远程服务时就必须使用 HTTP 客户端。Spring Boot 中使用的是 RestTemplate,首先,我们写一个配置类,将 RestTemplate 作为一个 Bean 交给 Spring 来管理 12345678@Configurationpublic class RestTmplateConfig { @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); }} 有了RestTmplate,接下来我们可以在 Controller 中注入该 RestTemplate 来调用 microservice-provider提供的服务了 12345678910111213141516171819202122//@RestController 相当于Controller注释加ResponesBody注释@RestController@RequestMapping(\"/consumer/order\")public class OrderConsumerController { // 订单服务提供者模块的 url 前缀 private static final String ORDER_PROVIDER_URL_PREFIX = \"http://localhost:8001\"; @Resource private RestTemplate restTemplate; @GetMapping(\"/get/{id}\") public TOrder getOrder(@PathVariable Long id) { return restTemplate.getForObject(ORDER_PROVIDER_URL_PREFIX + \"/provider/order/get/\" + id, TOrder.class); } @GetMapping(\"/get/list\") public List<TOrder> getAll() { return restTemplate.getForObject(ORDER_PROVIDER_URL_PREFIX + \"/provider/order/get/list\", List.class); }} 订单消费者模块搭建完了可以启动测试一下 浏览器访问: 1http://localhost:8080/consumer/order/get/list 返回结果,说明服务调用成功 可以看到通过订单消费者调用服务提供者暴露的服务,实现了每个服务专注于自身的逻辑,服务之间解耦合。 总结流程订单消费模块不直接请求数据库,而是通过 http 远程调用订单提供模块的服务来获取订单信息。也就是说,在微服务里,每个服务只关注自身的逻辑和实现,不用管其他服务的实现,需要获取某个服务的数据时,只要调用该服务提供的接口即可获取相应的数据。实现了每个服务专注于自身的逻辑,服务之间解耦合; 扩展Eureka整合1https://blog.csdn.net/weixin_40902527/article/details/88953312 Ribbon整合1https://blog.csdn.net/weixin_40902527/article/details/88977376 feign整合1https://blog.csdn.net/weixin_40902527/article/details/89249172 微服务框架Dubbo和Spring cloud差异1https://blog.csdn.net/weixin_40902527/article/details/88579521 代码地址:github地址","tags":[{"name":"JAVA","slug":"JAVA","permalink":"http://yoursite.com/tags/JAVA/"}]},{"title":" Java|设计模式总结","date":"2020-04-06T02:40:00.000Z","path":"2020/04/06/java/","text":"设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出命令模式123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354package com.designpatter.demo; /**** * 设计模式 * * 命令模式 * 命令(Command)模式的定义如下:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通, * 这样方便将命令对象进行储存、传递、调用、增加与管理。 * * 命令模式的主要优点如下。 * 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。 * 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。 * 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。 * 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。 * * 其缺点是:可能产生大量具体命令类。因为计对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。 */public class CommandPatterDemo { public static void main(String[] args) { Context command = new Context(new read()); command.execute(); } public interface Command { void execute(); } public static class read implements Command{ @Override public void execute() { System.out.println(\"开始读取数据\"); } } public static class copy implements Command{ @Override public void execute() { System.out.println(\"开始复制数据\"); } } public static class Context{ private Command command; public Context(Command command) { this.command = command; } public void execute(){ this.command.execute(); } }} 装饰模式1234567891011121314151617181920212223242526272829303132333435363738394041package com.designpatter.demo; /** * 装饰模式 * * 介绍其适用的应用场景,装饰模式通常在以下几种情况使用。 * 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。 * 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。 * 当对象的功能要求可以动态地添加,也可以再动态地撤销时。 * * 装饰模式在 Java 语言中的最著名的应用莫过于 Java I/O 标准库的设计了。例如,InputStream 的子类 FilterInputStream, * OutputStream 的子类 FilterOutputStream,Reader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriter、 * FilterWriter 以及 PrintWriter 等,它们都是抽象装饰类。 * */public class DecoratePatternDemo { public static void main(String[] args) { SuperPerson superPerson = new SuperPerson(new Person()); superPerson.eat(); } static class Person{ public void eat(){ System.out.println(\"吃饭\"); } } static class SuperPerson{ private Person person; public SuperPerson(Person person) { this.person = person; } public void eat(){ System.out.println(\"喝两口\"); this.person.eat(); System.out.println(\"抽两根\"); } }} 构建者模式123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103package com.designpatter.demo;/** * * 建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。 * 它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。 * * 该模式的主要优点如下: * 各个具体的建造者相互独立,有利于系统的扩展。 * 客户端不必知道产品内部组成的细节,便于控制细节风险。 * * 其缺点如下: * 产品的组成部分必须相同,这限制了其使用范围。 * 如果产品的内部变化复杂,该模式会增加很多的建造者类。 * * 建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。 * */public class WithoutPatternDemo { public static void main(String[] args) { Student student = new ConCreateStudent() .setSpeak1(\"test1\") .setSpeak2(\"test2\") .setSpeak3(\"test3\") .build(); System.out.println(student); } public static class Student{ private String speak1; private String speak2; private String speak3; public void setSpeak1(String speak1) { this.speak1 = speak1; } public void setSpeak2(String speak2) { this.speak2 = speak2; } public void setSpeak3(String speak3) { this.speak3 = speak3; } public String getSpeak1() { return speak1; } public String getSpeak2() { return speak2; } public String getSpeak3() { return speak3; } @Override public String toString() { return \"Student{\" + \"speak1='\" + speak1 + '\\'' + \", speak2='\" + speak2 + '\\'' + \", speak3='\" + speak3 + '\\'' + '}'; } } public interface Buidler{ Buidler setSpeak1(String speak1); Buidler setSpeak2(String speak2); Buidler setSpeak3(String speak3); Student build(); } public static class ConCreateStudent implements Buidler { Student student = new Student(); @Override public Buidler setSpeak1(String speak1) { System.out.println(\"复杂的逻辑判断\"); student.setSpeak1(speak1); return this; } @Override public Buidler setSpeak2(String speak2) { System.out.println(\"复杂的逻辑判断\"); student.setSpeak2(speak2); return this; } @Override public Buidler setSpeak3(String speak3) { System.out.println(\"复杂的逻辑判断\"); student.setSpeak3(speak3); return this; } @Override public Student build() { return student; } }} 组合模式1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768package com.designpatter.demo; import java.util.ArrayList;import java.util.List;/** * 组合模式的主要优点有: * 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码; * 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”; * * 其主要缺点是: * 设计较复杂,客户端需要花更多时间理清类之间的层次关系; * 不容易限制容器中的构件; * 不容易用继承的方法来增加构件的新功能; * */public class WhihoutPatternDemo { public static void main(String[] args) { Department coreDep = new Department(\"主部门\"); Department subDep1 = new Department(\"子部门1\"); Department subDep2 = new Department(\"子部门2\"); Department leafDep1 = new Department(\"叶子部门1\"); Department leafDep2 = new Department(\"叶子部门2\"); Department leafDep3 = new Department(\"叶子部门3\"); subDep1.child.add(leafDep1); subDep2.child.add(leafDep2); subDep2.child.add(leafDep3); coreDep.child.add(subDep1); coreDep.child.add(subDep2); coreDep.remove(); } static class Department{ private String name; private List<Department> child = new ArrayList<Department>(); public Department(String name) { this.name = name; } public String getName() { return name; } public List<Department> getChild() { return child; } public void setName(String name) { this.name = name; } public void setChild(List<Department> child) { this.child = child; } void remove(){ if(this.child.size() > 0){ for(Department department:this.child){ department.remove(); } } System.out.println(\"删除\"+name); } }} 程序开发遵守原则1.开闭原则定义:当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。 作用:开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性和延续性。具体来说,其作用如下。 对软件测试的影响软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。可以提高代码的可复用性粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。可以提高软件的可维护性遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。实现:可以通过“抽象约束、封装变化”来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。 2.里氏替换原则定义: 里氏替换原则主要阐述了有关继承的一些原则,也就是什么时候应该使用继承,什么时候不应该使用继承,以及其中蕴含的原理。里氏替换原是继承复用的基础,它反映了基类与子类之间的关系,是对开闭原则的补充,是对实现抽象化的具体步骤的规范。 作用: 里氏替换原则是实现开闭原则的重要方式之一。 它克服了继承中重写父类造成的可复用性变差的缺点。 它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。实现: 里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。如果程序违背了里氏替换原则,则继承类的对象在基类出现的地方会出现运行错误。这时其修正方法是:取消原来的继承关系,重新设计它们之间的关系。 3.依赖倒置原则定义:依赖倒置原则的原始定义为:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象(High level modules shouldnot depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details. Details should depend upon abstractions)。其核心思想是:要面向接口编程,不要面向实现编程。 依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。 作用: 依赖倒置原则可以降低类间的耦合性。 依赖倒置原则可以提高系统的稳定性。 依赖倒置原则可以减少并行开发引起的风险。 依赖倒置原则可以提高代码的可读性和可维护性。实现: 每个类尽量提供接口或抽象类,或者两者都具备。 变量的声明类型尽量是接口或者是抽象类。 任何类都不应该从具体类派生。 使用继承时尽量遵循里氏替换原则。 4.单一职责原则 定义:一个职责的变化可能会削弱或者抑制这个类实现其他职责的能力;当客户端需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代码或代码的浪费。 作用: 降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。 提高类的可读性。复杂性降低,自然其可读性会提高。 提高系统的可维护性。可读性提高,那自然更容易维护了。 变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其 他功能的影响实现:单一职责原则是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,再封装到不同的类或模块中。而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。下面以大学学生工作管理程序为例介绍单一职责原则的应用. 5.接口隔离原则定义: 单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离。 单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序整体框架的构建。作用: 将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。 接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。 如果接口的粒度大小定义合理,能够保证系统的稳定性;但是,如果定义过小,则会造成接口数量过多,使设计复杂化;如果定义太大,灵活性降低,无法提供定制服务,给整体项目带来无法预料的风险。 使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。 能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余的代码。实现: 接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。 为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。 了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同深入了解业务逻辑。 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。 6.迪米特原则 定义:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。 作用: 降低了类之间的耦合度,提高了模块的相对独立性。 由于亲合度降低,从而提高了类的可复用率和系统的扩展性。实现: 在类的划分上,应该创建弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标。 在类的结构设计上,尽量降低类成员的访问权限。 在类的设计上,优先考虑将一个类设置成不变类。 在对其他类的引用上,将引用其他对象的次数降到最低。 不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法)。 谨慎使用序列化(Serializable)功能。 7.合成复用原则定义:它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。作用: 它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。 新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的唯一方法是通过成分对象的接口。 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。实现: 合成复用原则是通过将已有的对象纳入新对象中,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用 23种设计模式 1234567891011121314151617181920212223 单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。 * 23种设计模式以及设计原则","tags":[{"name":"JAVA","slug":"JAVA","permalink":"http://yoursite.com/tags/JAVA/"}]}]
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/lzhengms/zhangti0708.github.io.git
git@gitee.com:lzhengms/zhangti0708.github.io.git
lzhengms
zhangti0708.github.io
zhangti0708.github.io
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891