forked from shihua-guo/shihua-guo.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
233 lines (131 loc) · 66 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Alan</title>
<icon>https://www.gravatar.com/avatar/61f9dbc3b48f389230fb9e02443ed31c</icon>
<link href="/atom.xml" rel="self"/>
<link href="http://haojen.github.io/"/>
<updated>2018-06-30T04:16:10.000Z</updated>
<id>http://haojen.github.io/</id>
<author>
<name>Alan</name>
<email>[email protected]</email>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>arcgis绘制功能</title>
<link href="http://haojen.github.io/2018/06/28/arcgis-draw/"/>
<id>http://haojen.github.io/2018/06/28/arcgis-draw/</id>
<published>2018-06-28T11:47:59.000Z</published>
<updated>2018-06-30T04:16:10.000Z</updated>
<content type="html"><![CDATA[<h2 id="arcgis绘制功能"><a href="#arcgis绘制功能" class="headerlink" title="arcgis绘制功能"></a>arcgis绘制功能</h2><blockquote><p>基于api 3.24</p></blockquote><h3 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h3><p>最近需要做一个地图小工具(测距、侧面积、缓冲区分析)的需求。客户说只要arcgis自带的工具就可以了。然而,项目的图层比较复杂,而且arcgis自带的工具几乎不能定制,所以我并有考虑直接使用自带的工具。所以我的思路如下:</p><ol><li>使用arcgis javascript api 的Draw工具( <a href="https://developers.arcgis.com/javascript/3/jsapi/draw-amd.html" target="_blank" rel="external"><strong>esri/toolbars/draw</strong> </a>),主要功能是绘制出点线面。</li><li>然后再计算绘制出来的图形,这里需要使用geometryEngine( <a href="https://developers.arcgis.com/javascript/3/jsapi/esri.geometry.geometryengine-amd.html" target="_blank" rel="external"><strong>esri/geometry/geometryEngine</strong></a> 3.13才添加的新工具 ),主要功能是计算对应的图形长度面积等。这里也可以使用arcgis server里面的服务来代替。</li></ol><p>下面说下实现的步骤:</p><ul><li><p>使用Draw工具绘制图形(<a href="https://developers.arcgis.com/javascript/3/jssamples/#search/Draw" target="_blank" rel="external">官网实例代码</a>)。</p><blockquote><p>new出draw工具—>定义绘制完成的回调函数—>在对应地方添加触发绘制的事件</p></blockquote><ol><li><p>引入对应的draw <strong>esri/toolbars/draw</strong> ,定义draw工具</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">var</span> draw = <span class="keyword">new</span> Draw(map);</div></pre></td></tr></table></figure></li><li><p>定义绘制完成的回调函数</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">var</span> draw = <span class="keyword">new</span> Draw(map);</div><div class="line"><span class="comment">/**</span></div><div class="line"><span class="comment"> on(type: "draw-complete", listener: (event: { geometry: Geometry; target: Draw }) => void): esri.Handle;</span></div><div class="line"><span class="comment"> 回调函数的参数有:绘制完成图形的对应的地理信息:geometry,以及整个draw对象。</span></div><div class="line"><span class="comment"> */</span></div><div class="line">draw.on(<span class="string">"draw-complete"</span>,endDraw)</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">endDraw</span>(<span class="params">event</span>)</span>{</div><div class="line"> <span class="comment">//逻辑处理</span></div><div class="line">}</div></pre></td></tr></table></figure></li><li><p>在对应的dom触发对应的图形绘制,下面举例绘制点的例子。</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">var</span> draw = <span class="keyword">new</span> Draw(map);</div><div class="line"><span class="comment">/**</span></div><div class="line"><span class="comment"> on(type: "draw-complete", listener: (event: { geometry: Geometry; target: Draw }) => void): esri.Handle;</span></div><div class="line"><span class="comment"> 回调函数的参数有:绘制完成图形的对应的地理信息:geometry,以及整个draw对象。</span></div><div class="line"><span class="comment"> */</span></div><div class="line">draw.on(<span class="string">"draw-complete"</span>,endDraw)</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">endDraw</span>(<span class="params">event</span>)</span>{</div><div class="line"> <span class="comment">//逻辑处理</span></div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">var</span> ptDom = <span class="built_in">document</span>.getElementById(<span class="string">"ptDom"</span>)</div><div class="line">ptDom.addEventListener(<span class="string">"click"</span>, drawPoint, <span class="literal">false</span>); </div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">drawPoint</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">this</span>.draw.activate(Draw.POINT);</div><div class="line">}</div></pre></td></tr></table></figure><p>下面分别是开启绘制对应图形的代码,以及取消绘制,可以在对应的dom事件添加:</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">drawCircle</span>(<span class="params"></span>)</span>{<span class="comment">//绘制圆</span></div><div class="line"> <span class="keyword">this</span>.draw.activate(Draw.CIRCLE);</div><div class="line">}</div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">drawPolygon</span>(<span class="params"></span>)</span>{<span class="comment">//绘制多边形</span></div><div class="line"> <span class="keyword">this</span>.draw.activate(Draw.POLYGON);</div><div class="line">}</div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">drawPolyline</span>(<span class="params"></span>)</span>{<span class="comment">//绘制线</span></div><div class="line"> <span class="keyword">this</span>.draw.activate(Draw.POLYLINE);</div><div class="line">}</div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">endDraw</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">this</span>.draw.deactivate();</div><div class="line">}</div></pre></td></tr></table></figure></li></ol></li><li><p>测距、测面积的工具实现。引入工具geometryEngine <strong>esri/geometry/geometryEngine</strong>工具,这里需要在绘制完成的回调参数里面判断绘制的图形类型,然后再做对应处理。下面关注 <strong>endDraw</strong> 函数即可。</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">endDraw</span>(<span class="params">event</span>)</span>{</div><div class="line"> <span class="comment">//逻辑处理</span></div><div class="line"> <span class="keyword">var</span> result = <span class="literal">null</span>;</div><div class="line"> <span class="keyword">switch</span> (event.geometry.type) {</div><div class="line"> <span class="keyword">case</span> <span class="string">"point"</span>:</div><div class="line"> </div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">case</span> <span class="string">"polyline"</span>:</div><div class="line"> <span class="comment">//使用geodesicLength计算长度</span></div><div class="line"> result = GeometryEngine.geodesicLength(event.geometry,<span class="string">"kilometers"</span>);</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">case</span> <span class="string">"polygon"</span>:</div><div class="line"> <span class="comment">//使用geodesicArea计算面积</span></div><div class="line"> result = GeometryEngine.geodesicArea(event.geometry,<span class="string">"kilometers"</span>);</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"></div><div class="line"> <span class="keyword">default</span>:</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure><p>上面就能得到你需要的结果,然后再你想要的地方显示出来就可以了。</p></li><li><p>缓冲区分析工具实现。我们继续在回调函数 <strong>endDraw</strong> 处理。缓冲区分析,主要就是在绘制的范围内,筛选出该范围内的图形。主要是针对各种图层服务来做对应的处理。下面主要介绍:FeatureServer、以及featureCollection构建的FeatureLayer图层。</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line">...</div><div class="line"><span class="keyword">var</span> layer <span class="comment">//这里是你的各种图层</span></div><div class="line">...</div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">endDraw</span>(<span class="params">event</span>)</span>{</div><div class="line"> <span class="keyword">switch</span> (event.geometry.type) {</div><div class="line"> <span class="keyword">case</span> <span class="string">"polygon"</span>:</div><div class="line"> <span class="comment">//只有是多边形的才进行处理</span></div><div class="line"> <span class="keyword">switch</span> (layer.type) {</div><div class="line"> <span class="keyword">case</span> <span class="string">"Feature Layer"</span>:</div><div class="line"> <span class="keyword">if</span>(layer.url){<span class="comment">//如果是基于arcgis server的服务的FeatureLayer</span></div><div class="line"> <span class="comment">/* 引入"esri/tasks/query",可以直接调用服务的查询,非常方便 */</span></div><div class="line"> <span class="keyword">var</span> query = <span class="keyword">new</span> Query();</div><div class="line"> query.geometry = event.geometry;</div><div class="line"> query.outFields = [<span class="string">"OBJECTID"</span>];</div><div class="line"> <span class="keyword">var</span> queryTask = <span class="keyword">new</span> QueryTask(layer.layer.url);</div><div class="line"> <span class="keyword">var</span></div><div class="line"> queryTask.execute(query, (results: any) => {</div><div class="line"> <span class="comment">//results就是在绘制范围内的要素。</span></div><div class="line"> });</div><div class="line"> }<span class="keyword">else</span>{<span class="comment">//如果是基于featureCollection构建的FeatureLayer</span></div><div class="line"></div><div class="line"> }</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">default</span>:</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"></div><div class="line"> <span class="keyword">default</span>:</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></li></ul>]]></content>
<summary type="html">
<h2 id="arcgis绘制功能"><a href="#arcgis绘制功能" class="headerlink" title="arcgis绘制功能"></a>arcgis绘制功能</h2><blockquote>
<p>基于api 3.24</p>
</blockquo
</summary>
</entry>
<entry>
<title>arcgis导出</title>
<link href="http://haojen.github.io/2018/06/27/arcgis-export/"/>
<id>http://haojen.github.io/2018/06/27/arcgis-export/</id>
<published>2018-06-27T11:32:07.000Z</published>
<updated>2018-06-30T05:17:05.000Z</updated>
<content type="html"><![CDATA[<h1 id="arcgis导出"><a href="#arcgis导出" class="headerlink" title="arcgis导出"></a>arcgis导出</h1><blockquote><p>基于arcgis javascript api 3.24</p></blockquote><h3 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h3><p>最近需要做一个地图导出的需求。有大概一下2个要求:</p><ol><li>需要导出全市范围(也就是包括视野范围之外的也需要导出)</li><li>所见即所得,当前页面看到的和导出的一致。</li></ol><p>于是,我大致思路如下:</p><ol><li>使用arcgis自带的PrintTask工具</li><li>直接将整个地图“截图”下来,保存成图片再给客户。</li></ol><h3 id="使用PrintTask"><a href="#使用PrintTask" class="headerlink" title="使用PrintTask"></a>使用PrintTask</h3><p>使用PrintTask比较简单,官网也有例子。主要步骤如下:</p><ol><li><p>var printTask = new PrintTask(url);</p><blockquote><p>这里的url放的是这个工具的服务地址。<a href="http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task" target="_blank" rel="external">arcgis官网的工具地址</a>。<br>如果本地有arcserver,那么本地的地址可以到arcgisserver 后台管理查看,进入后台管理后,点击左边的 <strong>Utilities</strong> 然后看到 <strong>PrintingTools</strong> 就是了。</p></blockquote><p><img src="/img/arcgis-export/1.png" alt="后台管理查看"></p></li><li><p>var params = new PrintParameters();建立导出的模板PrintParameters,具体参数去api查看。并且设置map: params.map = map;</p></li><li><p>执行:printTask.execute(params, printResult=>{});这里会回调一个printResult,里面带有图片或者pdf等文件的下载地址。</p><blockquote><p>注意:导出可能会遇到超时问题。</p></blockquote></li></ol><p>但是呢,我遇到了以下问题:</p><ol><li><p>最严重的是,导出速度非常非常非常慢。经测试,最简单的导出需要3分钟左右。所以会遇到超时问题,这里需要设置一下esriConfig。代码如下:</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">import</span> esriConfig = <span class="built_in">require</span>(<span class="string">"esri/config"</span>)</div><div class="line">...</div><div class="line">esriConfig.defaults.io.timeout = <span class="number">300000</span>;<span class="comment">//这里设置你的超时时间</span></div></pre></td></tr></table></figure><blockquote><p>开始我以为是来源于PrintingTools服务的 <strong>客户端可使用服务的最长时间</strong> 设置造成的,其实并不是。是因为esri默认的请求时间是1分钟。</p></blockquote></li><li><p>导出的分辨率低,而且不能识别某些图层。比如我使用featureSet构建的图层。</p></li></ol><p>以上,PrintingTools导出的速度基本就判死刑了。经我们公司的arcgis人员使用arcserver导出也是非常慢。原因不得而知,cpu/内存占用几乎没变化,并且导出会提示内存不足,但是内存十分充足。</p><blockquote><p>所以在这里请教一下大家,服务器并没有显卡,是因为gpu的问题吗,才导出这么慢吗?所以,我今天选择了第二种方法:截图。</p></blockquote><h3 id="截图保存"><a href="#截图保存" class="headerlink" title="截图保存"></a>截图保存</h3><blockquote><p>有了这个想法,我就查了如何实现,并且查到相关的:<a href="https://www.jianshu.com/p/e7b82caa12b5" target="_blank" rel="external">arcgis api for js入门开发系列二十打印地图的那些事</a>。非常感谢!</p></blockquote><p>主要步骤如下:</p><ol><li><p>获取到地图的容器->将图层元素转化为canvas->下载。</p><blockquote><p>这里需要用到<a href="https://github.com/niklasvh/html2canvas" target="_blank" rel="external">html2canvas</a>。</p></blockquote><p>实现很简单,代码如下,(完全从上面的简书搬过来的),我重点是解决上面简书并没有提及的一些问题:</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line">canvasPrint=<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">var</span> targetDom = $(<span class="string">"#map"</span>);</div><div class="line"> <span class="comment">//克隆截图区域</span></div><div class="line"> <span class="keyword">var</span> copyDom = targetDom.clone();</div><div class="line"> copyDom.width(targetDom.width() + <span class="string">"px"</span>);</div><div class="line"> copyDom.height(targetDom.height() + <span class="string">"px"</span>);</div><div class="line"> copyDom.attr(<span class="string">"id"</span>, <span class="string">"copyDom"</span>);</div><div class="line"> $(<span class="string">"body"</span>).append(copyDom);</div><div class="line"> <span class="comment">//移除不需要截图的区域</span></div><div class="line"> $(<span class="string">".base-map"</span>).remove();</div><div class="line"> </div><div class="line"> <span class="keyword">var</span> pathName = <span class="built_in">document</span>.location.pathname;</div><div class="line"> <span class="keyword">var</span> ctxPath = pathName.substring(<span class="number">1</span>, pathName.substr(<span class="number">1</span>).indexOf(<span class="string">'/'</span>) + <span class="number">1</span>);</div><div class="line"> html2canvas(copyDom[<span class="number">0</span>], {</div><div class="line"> useCORS: <span class="literal">true</span>,</div><div class="line"> imageTimeout:<span class="number">0</span></div><div class="line"> <span class="comment">//, proxy: "/" + ctxPath + "/proxy/proxyScreenShot"</span></div><div class="line"> }).then(<span class="function"><span class="keyword">function</span> (<span class="params">canvas</span>) </span>{</div><div class="line"> <span class="keyword">var</span> url = canvas.toDataURL();</div><div class="line"> <span class="comment">//创建下载a标签</span></div><div class="line"> <span class="keyword">var</span> a = <span class="built_in">document</span>.createElement(<span class="string">"a"</span>);</div><div class="line"> a.setAttribute(<span class="string">"id"</span>, <span class="string">"download"</span>);</div><div class="line"> <span class="built_in">document</span>.body.appendChild(a);</div><div class="line"> <span class="comment">//以下代码为下载此图片功能</span></div><div class="line"> <span class="keyword">var</span> triggerDownload = $(<span class="string">"#download"</span>).attr(<span class="string">"href"</span>, url).attr(<span class="string">"download"</span>, <span class="string">"img.png"</span>);</div><div class="line"> triggerDownload[<span class="number">0</span>].click();</div><div class="line"> <span class="comment">//移除下载a标签</span></div><div class="line"> <span class="built_in">document</span>.body.removeChild(a);</div><div class="line"> <span class="comment">//克隆DOM删除</span></div><div class="line"> copyDom.remove();</div><div class="line"> });</div><div class="line">}</div></pre></td></tr></table></figure></li><li><p>会出现以下问题</p><ol><li><p>问题1:<strong>图层会和底图出现偏移</strong>,如图:<br><img src="/img/arcgis-export/2.png" alt="偏移"></p><p>为什么会出现偏移呢? <strong>因为html2canvas转化成canvas的时候并<a href="https://github.com/niklasvh/html2canvas/issues/220" target="_blank" rel="external">不支持transform</a></strong><br>我们看看各个图层在dom是如何构成:<br><img src="/img/arcgis-export/3.png" alt="构成"></p><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">viewDiv(定义的地图div)</div><div class="line">│</div><div class="line">└───viewDiv_root</div><div class="line"> └───viewDiv_container</div><div class="line"> └───viewDiv_layers(存放地图的div)</div></pre></td></tr></table></figure><p>可以看到,在我们没有移动地图时,viewDiv_layers的transform都为0px;而这时候转化的canvas是并没有偏移的。<br><img src="/img/arcgis-export/4.png" alt="没有偏移"><br>但是,当我们拖动地图的时候,viewDiv_layers的transform开始变化。所以,html2canvas并没有将transform渲染上去。<br><img src="/img/arcgis-export/5.png" alt="变化"></p><p><strong>我们可以在导出前重新加载地图,来去除偏移</strong></p><blockquote><p>因为代码结合了较多的业务,所以放代码也没有多大的意义,就放伪代码吧。个人也懒的重新写一个。 </p></blockquote><ol><li><p>保存当前地图中心点位置以及缩放(就是拖动地图之后的中心点位置以及缩放)</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">var</span> center = <span class="keyword">this</span>.map.extent.getCenter();</div><div class="line"><span class="keyword">var</span> zoom = <span class="keyword">this</span>.map.getZoom();</div></pre></td></tr></table></figure></li><li><p>使用上一次的中心点和缩放,重新new一遍地图。</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">const</span> esriMap = <span class="keyword">new</span> EsriMap(<span class="string">"viewDiv"</span>, {</div><div class="line"> center: center,</div><div class="line"> zoom: zoom,</div><div class="line">});</div></pre></td></tr></table></figure></li><li><p>这时候,就可以看到transform都变为0了。就可以放心导出了。</p></li></ol></li><li><p>问题2:当文件过大,下载的时候会出现。<strong>失败,网络错误的提示</strong>。</p><blockquote><p>这里有一个<a href="https://stackoverflow.com/questions/37135417/download-canvas-as-png-in-fabric-js-giving-network-error/" target="_blank" rel="external">相关答案</a></p></blockquote><p>这时候不用担心,不是代码有问题,也不是html2canvas问题。上面,我们是用base64来进行下载的,而谷歌浏览器限制了donwload属性的a标签url长度。<strong>这时候我们可以将html2canvas转化为blob,再使用一个插件: <a href="https://github.com/eligrey/FileSaver.js/" target="_blank" rel="external">FileSaver</a>进行下载</strong> ,代码如下,只需要在返回canvas的代码块中修改一下就可以了:</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"> canvasPrint=<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">var</span> targetDom = $(<span class="string">"#map"</span>);</div><div class="line"> <span class="comment">/* 克隆截图区域 */</span></div><div class="line"> <span class="keyword">var</span> copyDom = targetDom.clone();</div><div class="line"> copyDom.width(targetDom.width() + <span class="string">"px"</span>);</div><div class="line"> copyDom.height(targetDom.height() + <span class="string">"px"</span>);</div><div class="line"> copyDom.attr(<span class="string">"id"</span>, <span class="string">"copyDom"</span>);</div><div class="line"> $(<span class="string">"body"</span>).append(copyDom);</div><div class="line"> <span class="comment">/* 移除不需要截图的区域 */</span></div><div class="line"> $(<span class="string">".base-map"</span>).remove();</div><div class="line"> <span class="keyword">var</span> pathName = <span class="built_in">document</span>.location.pathname;</div><div class="line"> <span class="keyword">var</span> ctxPath = pathName.substring(<span class="number">1</span>, pathName.substr(<span class="number">1</span>).indexOf(<span class="string">'/'</span>) + <span class="number">1</span>);</div><div class="line"> html2canvas(copyDom[<span class="number">0</span>], {</div><div class="line"> useCORS: <span class="literal">true</span>,</div><div class="line"> imageTimeout:<span class="number">0</span></div><div class="line"> <span class="comment">/* , proxy: "/" + ctxPath + "/proxy/proxyScreenShot" */</span></div><div class="line"> }).then(<span class="function"><span class="keyword">function</span> (<span class="params">canvas</span>) </span>{</div><div class="line"> <span class="comment">/* --------------修改部分----------------------- */</span></div><div class="line"> canvas.toBlob(<span class="function"><span class="keyword">function</span>(<span class="params">blob</span>) </span>{</div><div class="line"> FileSaver.saveAs(blob, <span class="string">"image.png"</span>);</div><div class="line"> });</div><div class="line"> <span class="comment">/* --------------修改部分----------------------- */</span></div><div class="line"> <span class="comment">/* 克隆DOM删除 */</span></div><div class="line"> copyDom.remove();</div><div class="line"> });</div><div class="line">}</div></pre></td></tr></table></figure></li><li><p>问题3:<strong>无法导出featureLayer的图层</strong>。如图,我们需要出现的房子并没有出现:<br><img src="/img/arcgis-export/8.png" alt="1"><br>为什么呢?我们再来看看各个图层在dom是如何构成:<br><img src="/img/arcgis-export/9.png" alt="1"><br>以上,可以看到要素图层是存放于svg里面,而每一个graphic都存放于image标签内。这样就构建成了一个要素图层。<br>所以,这有什么关系呢?你可能需要更新一下html2canvas,因为从<a href="https://github.com/niklasvh/html2canvas/releases/tag/0.5.0-alpha1" target="_blank" rel="external">0.5.0-alpha1</a>版本才开始支持svg渲染,而且html2canvas会忽略<a href="https://stackoverflow.com/questions/40969900/html2canvas-ignores-my-svg-elements/51056005#51056005" target="_blank" rel="external">svg元素</a>,不过只需要添加一下 <strong>allowTaint: true</strong> 属性就可以了。</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"> canvasPrint=<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">var</span> targetDom = $(<span class="string">"#map"</span>);</div><div class="line"> <span class="comment">/* 克隆截图区域 */</span></div><div class="line"> <span class="keyword">var</span> copyDom = targetDom.clone();</div><div class="line"> copyDom.width(targetDom.width() + <span class="string">"px"</span>);</div><div class="line"> copyDom.height(targetDom.height() + <span class="string">"px"</span>);</div><div class="line"> copyDom.attr(<span class="string">"id"</span>, <span class="string">"copyDom"</span>);</div><div class="line"> $(<span class="string">"body"</span>).append(copyDom);</div><div class="line"> <span class="comment">/* 移除不需要截图的区域 */</span></div><div class="line"> $(<span class="string">".base-map"</span>).remove();</div><div class="line"> <span class="keyword">var</span> pathName = <span class="built_in">document</span>.location.pathname;</div><div class="line"> <span class="keyword">var</span> ctxPath = pathName.substring(<span class="number">1</span>, pathName.substr(<span class="number">1</span>).indexOf(<span class="string">'/'</span>) + <span class="number">1</span>);</div><div class="line"> html2canvas(copyDom[<span class="number">0</span>], {</div><div class="line"> useCORS: <span class="literal">true</span>,</div><div class="line"> imageTimeout:<span class="number">0</span>,</div><div class="line"> <span class="comment">/* --------------修改部分----------------------- */</span></div><div class="line"> allowTaint: <span class="literal">true</span></div><div class="line"> <span class="comment">/* --------------修改部分----------------------- */</span></div><div class="line"> <span class="comment">/* , proxy: "/" + ctxPath + "/proxy/proxyScreenShot" */</span></div><div class="line"> }).then(<span class="function"><span class="keyword">function</span> (<span class="params">canvas</span>) </span>{</div><div class="line"> canvas.toBlob(<span class="function"><span class="keyword">function</span>(<span class="params">blob</span>) </span>{</div><div class="line"> FileSaver.saveAs(blob, <span class="string">"image.png"</span>);</div><div class="line"> });</div><div class="line"> <span class="comment">/* 克隆DOM删除 */</span></div><div class="line"> copyDom.remove();</div><div class="line"> });</div><div class="line">}</div></pre></td></tr></table></figure><p>以上允许了渲染svg,如果没有意外,下载的时候会出现以下错误:</p><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.</div></pre></td></tr></table></figure><p>看html2canvas源码发现,貌似如果开启了支持svg,会执行以下代码。</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">var</span> testSVG = <span class="function"><span class="keyword">function</span> <span class="title">testSVG</span>(<span class="params">document</span>) </span>{</div><div class="line"><span class="keyword">var</span> img = <span class="keyword">new</span> Image();</div><div class="line"><span class="keyword">var</span> canvas = <span class="built_in">document</span>.createElement(<span class="string">'canvas'</span>);</div><div class="line"><span class="keyword">var</span> ctx = canvas.getContext(<span class="string">'2d'</span>);</div><div class="line">img.src = <span class="string">'data:image/svg+xml,<svg xmlns=\'http://www.w3.org/2000/svg\'></svg>'</span>;</div><div class="line"></div><div class="line"><span class="keyword">try</span> {</div><div class="line"> ctx.drawImage(img, <span class="number">0</span>, <span class="number">0</span>);</div><div class="line"> canvas.toDataURL();</div><div class="line">} <span class="keyword">catch</span> (e) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line">}</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line">};</div></pre></td></tr></table></figure><p>就是将svg拿到然后drawImage将svg图片绘制进canvas。这里,如果new的img标签没有设置 <strong>crossOrigin</strong> 属性为 <strong>anonymous</strong> 那么<a href="https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror" target="_blank" rel="external">谷歌浏览器会不允许执行canvas.toDataURL()和toBlob()方法</a>。因为画布被污染了。</p><p>解决思路:</p><blockquote><p>我觉可以将image标签添设置 <strong>crossOrigin</strong> 属性为 <strong>anonymous</strong> 就可以导出咯。但是这些都是arcgis生成的。我并没有试过。或者可以修改html2canvas的源码?不过,因为思维局限,我想到了另外一种方法:将svg部分转化为image->再将image写入到canvas</p></blockquote><ol><li>将svg部分转化为image,这里我用了<a href="https://github.com/exupero/saveSvgAsPng" target="_blank" rel="external">saveSvgAsPng</a>插件,再将image写入到canvas。<figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"> canvasPrint=<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">var</span> targetDom = $(<span class="string">"#map"</span>);</div><div class="line"> <span class="comment">/* 克隆截图区域 */</span></div><div class="line"> <span class="keyword">var</span> copyDom = targetDom.clone();</div><div class="line"> copyDom.width(targetDom.width() + <span class="string">"px"</span>);</div><div class="line"> copyDom.height(targetDom.height() + <span class="string">"px"</span>);</div><div class="line"> copyDom.attr(<span class="string">"id"</span>, <span class="string">"copyDom"</span>);</div><div class="line"> $(<span class="string">"body"</span>).append(copyDom);</div><div class="line"> <span class="comment">/* 移除不需要截图的区域 */</span></div><div class="line"> $(<span class="string">".base-map"</span>).remove();</div><div class="line"></div><div class="line"> <span class="comment">/* --------------修改部分----------------------- */</span></div><div class="line"> <span class="comment">/* 转换svg,找到对应的svg元素,再设置crossOrigin */</span></div><div class="line"> <span class="keyword">let</span> dom = <span class="built_in">document</span>.querySelector(<span class="string">"#viewDiv_layers svg"</span>);</div><div class="line"> <span class="keyword">let</span> img = <span class="keyword">new</span> Image();</div><div class="line"> saveSvgAsPng.svgAsDataUri(dom,{}, (uri:any)=>{</div><div class="line"> img.src = uri;</div><div class="line"> <span class="comment">/* 这里是重点 */</span></div><div class="line"> img.setAttribute(<span class="string">"crossOrigin"</span>,<span class="string">'anonymous'</span>)</div><div class="line"> });</div><div class="line"> <span class="comment">/* --------------修改部分----------------------- */</span></div><div class="line"></div><div class="line"> <span class="keyword">var</span> pathName = <span class="built_in">document</span>.location.pathname;</div><div class="line"> <span class="keyword">var</span> ctxPath = pathName.substring(<span class="number">1</span>, pathName.substr(<span class="number">1</span>).indexOf(<span class="string">'/'</span>) + <span class="number">1</span>);</div><div class="line"> html2canvas(copyDom[<span class="number">0</span>], {</div><div class="line"> useCORS: <span class="literal">true</span>,</div><div class="line"> imageTimeout:<span class="number">0</span>,</div><div class="line"> <span class="comment">/* , proxy: "/" + ctxPath + "/proxy/proxyScreenShot" */</span></div><div class="line"> }).then(<span class="function"><span class="keyword">function</span> (<span class="params">canvas</span>) </span>{</div><div class="line"></div><div class="line"> <span class="comment">/* --------------修改部分----------------------- */</span></div><div class="line"> <span class="keyword">let</span> ctx = canvas.getContext(<span class="string">"2d"</span>) <span class="comment">/* 对应的CanvasRenderingContext2D对象(画笔) */</span></div><div class="line"> ctx.drawImage(img,<span class="number">0</span>,<span class="number">0</span>); </div><div class="line"> <span class="comment">/* --------------修改部分----------------------- */</span></div><div class="line"></div><div class="line"> canvas.toBlob(<span class="function"><span class="keyword">function</span>(<span class="params">blob</span>) </span>{</div><div class="line"> FileSaver.saveAs(blob, <span class="string">"image.png"</span>);</div><div class="line"> });</div><div class="line"> <span class="comment">/* 克隆DOM删除 */</span></div><div class="line"> copyDom.remove();</div><div class="line"> });</div><div class="line">}</div></pre></td></tr></table></figure></li></ol><p>以上,就能解决了。</p></li><li><p>问题5:如何在地图放大之后,导出包括视野范围外的整张地图。大致步骤:导出前修改dom的宽度和高度->触发地图更新->导出<br>导出前进行对地图dom的width和height进行调整。<br>明确一下:每一次对地图的zoom,width和height都会*2,所以计算每次zoom是2的(zoom差值的次方)。</p><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="comment">/* </span></div><div class="line"><span class="comment">zoomOrigin(原始放大级别),zoomChange(当前放大级别)</span></div><div class="line"><span class="comment">widthOrigin(原始放宽度)</span></div><div class="line"><span class="comment">heightOrigin(原始高度)</span></div><div class="line"><span class="comment">关系如下:</span></div><div class="line"><span class="comment">width = widthOrigin * Math.pow(2,(zoomOrigin-zoomChange))</span></div><div class="line"><span class="comment">height = heightOrigin * Math.pow(2,(zoomOrigin-zoomChange))</span></div><div class="line"><span class="comment"> */</span></div><div class="line"><span class="keyword">var</span> zoomOrigin;</div><div class="line">...</div><div class="line"><span class="keyword">var</span> zoomChange = <span class="keyword">this</span>.map.getZoom();</div><div class="line"><span class="keyword">var</span> dom = <span class="built_in">document</span>.getElementById(<span class="string">"viewDiv"</span>);</div><div class="line">dom.style.width = dom.style.width * <span class="built_in">Math</span>.pow(<span class="number">2</span>,(zoomOrigin-zoomChange))</div><div class="line">dom.style.width = dom.style.width * <span class="built_in">Math</span>.pow(<span class="number">2</span>,(zoomOrigin-zoomChange))</div><div class="line"><span class="comment">/* dom发生变化之后地图会自动进行调整,这里由于宽度和高度是向右下扩展的,</span></div><div class="line"><span class="comment"> 所以,我们需要重新定位中心点,这里需要监听map的更新完成事件,再进行中心点调整 */</span></div><div class="line">...</div><div class="line"><span class="keyword">var</span> center;<span class="comment">/* 原来记录好的中心点*/</span></div><div class="line"><span class="keyword">var</span> updateEvent = <span class="keyword">this</span>.map.on(<span class="string">"update-end"</span>,<span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>{</div><div class="line"> <span class="keyword">this</span>.map = <span class="keyword">new</span> EsriMap(<span class="string">"viewDiv"</span>, {</div><div class="line"> center: center,</div><div class="line"> zoom: zoomChange,</div><div class="line"> });</div><div class="line"> updateEvent.remove();<span class="comment">/* 移除事件监听 */</span></div><div class="line">})</div><div class="line">...</div><div class="line"><span class="comment">//之后进行导出即可</span></div></pre></td></tr></table></figure></li><li><p>问题4:使用瓦片服务,会出现跨域问题。地图会空白,如图,左边为需要的效果,右边为实际效果。<br><img src="/img/arcgis-export/12.png" alt="试试"></p><p>一般都会有代理软件吧,所以其实只要把瓦片服务代理一下就可以了。用Apache或者Nginx等都可以。</p></li></ol><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>总的来说,如果用“截图”的方式导出。需要使用html2canvas插件,然后再解决偏移、下载、要素图层无法渲染的问题即可。</p></li></ol>]]></content>
<summary type="html">
<h1 id="arcgis导出"><a href="#arcgis导出" class="headerlink" title="arcgis导出"></a>arcgis导出</h1><blockquote>
<p>基于arcgis javascript api 3.24</p>
</summary>
</entry>
<entry>
<title>functional programming</title>
<link href="http://haojen.github.io/2018/03/26/functional-programming/"/>
<id>http://haojen.github.io/2018/03/26/functional-programming/</id>
<published>2018-03-26T14:02:21.000Z</published>
<updated>2018-04-20T15:59:54.000Z</updated>
<content type="html"><![CDATA[<h1 id="Functional-Programming"><a href="#Functional-Programming" class="headerlink" title="Functional Programming"></a>Functional Programming</h1><blockquote><p>仅仅是一篇观后感</p></blockquote><p>最近在我违反了 <strong>no mutation</strong> ,既在一个函数里面修改了传入的变量。导致我在另外一个地方使用该变量的时候,并不知道它已经发生了变化。然后,我突然想起了好几个月前看得一个演讲:<a href="https://www.youtube.com/watch?v=e-5obm1G_FY" target="_blank" rel="external">Anjana Vakil: Learning Functional Programming with JavaScript - JSUnconf 2016</a>。这里面就有讲什么是 <strong>Functional Programming</strong>。我发现,在JS中,遵循了下面几条原则,可以更好的复用、维护代码。</p><blockquote><p>在平时写业务的过程中设计模式是谈不上了,但是Functional Programming恰处处可见。</p></blockquote><h3 id="What-is-Functional-Programming"><a href="#What-is-Functional-Programming" class="headerlink" title="What is Functional Programming?"></a>What is Functional Programming?</h3><p>什么是Functional Programming<br>A programming paradigm.<br>一种编程的范式。就像<strong>面向过程</strong>、<strong>面向对象</strong>(狗.吃(屎))。总的来说,<strong>Function is King</strong></p><blockquote><p>如果说<strong>面向过程</strong>就类似于(吃(狗,屎))、<strong>面向对象</strong>类似于(狗.吃(屎)),那么Functional Programming可以初略概括为:狗.吃(屎) -> 屎,因为只有input和output才算是一个合格的function。</p></blockquote><p>A code style.<br>一种代码的风格。如何去组织你的代码。</p><p>A mindset.<br>一种思维模式。该使用什么样的方式去解决你的问题?就像你不想去破解一个代码块完整性(内聚),那么你可以加入一个切面,去影响该代码块的执行结果。</p><p>A sexy, buzz-wordy trend.</p><h3 id="Why-Functional-Javascript"><a href="#Why-Functional-Javascript" class="headerlink" title="Why Functional Javascript?"></a>Why Functional Javascript?</h3><p>Object-oriented in javascript gets tricky.<br>因为在JavaScript中,面向对象往往纠缠不清。就比如this.貌似真的很多时候,this的指向会变化多端。</p><p>Safer, easier to debug/maintain.</p><p>Established community.</p><h3 id="How-Functional-Programming-in-Javascript"><a href="#How-Functional-Programming-in-Javascript" class="headerlink" title="How Functional Programming in Javascript?"></a>How Functional Programming in Javascript?</h3><p>Do everything in function.<br>非常简单,就是一个input->output的过程。你只需要简单的把input交给一个function处理,然后它会给你需要的output。就像一种数据的流向。有以下的</p><h6 id="以下是非Functional的形式(A):"><a href="#以下是非Functional的形式(A):" class="headerlink" title="以下是非Functional的形式(A):"></a>以下是非Functional的形式(A):</h6><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">var name = "Alan";</div><div class="line">var greeting = "Hi,I'm ";</div><div class="line">console.log(greeting+name);</div><div class="line">=> "Hi,I'm Alan"</div></pre></td></tr></table></figure><h6 id="以下是Functional的形式(B):"><a href="#以下是Functional的形式(B):" class="headerlink" title="以下是Functional的形式(B):"></a>以下是Functional的形式(B):</h6><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">function greet(name){</div><div class="line"> return "Hi,I'm "+name;</div><div class="line">}</div><div class="line">greet("alan");</div><div class="line">=> "Hi,I'm Alan"</div></pre></td></tr></table></figure><p>例子A中,处理形式就是定义完greet,然后定义name,然后一起输出。而例子B,是将name交给一个greet函数处理,它会返回拼接一个greet然后返回给你。</p><p>Use pure function.<br>在Functional Programming中,我们会遇到一个问题:function a中,改变了input的内容,然后你在其他的function b中使用该input的时候,发现它已经被改变,然后也许function b中的执行结果会因为function a中改变了input而改变。这个就是文章开头提及的情况。这时候,你可能会绞尽脑汁,究竟在哪里改变了它。所以,纯净的function是不应该去改变input的。你应该在一个function里面拿了input,然后只读取input然后计算output,然后把output返回。<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">var name = "alan";</div><div class="line">function greet(){</div><div class="line"> name = "jade";</div><div class="line"> return "Hi,I'm "+name;</div><div class="line">}</div><div class="line">function sayMyName(name){</div><div class="line"> return "Hi,I'm "+name;</div><div class="line">}</div><div class="line">greet();</div><div class="line">sayMyName(name);</div></pre></td></tr></table></figure></p><p>同样,以下也不是纯净的function<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">var name = "alan";</div><div class="line">function greet(){</div><div class="line"> console.log("Hi,I'm "+name);</div><div class="line">}</div></pre></td></tr></table></figure></p><p>并没有input,直接使用了全局的变量。而且并没有返回计算的结果,我们需要的是function帮我们计算并返回结果,打印并不是function需要做的事情。正确做法应该如下,function唯一需要做的就是使用input去计算得出我们需要的output,并将output返回:<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">var name = "alan";</div><div class="line">function greet(name){</div><div class="line"> return "Hi,I'm "+name;</div><div class="line">}</div></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<h1 id="Functional-Programming"><a href="#Functional-Programming" class="headerlink" title="Functional Programming"></a>Functional Programmi
</summary>
</entry>
<entry>
<title>使用七牛chrome插件上传图片</title>
<link href="http://haojen.github.io/2018/03/22/%E4%BD%BF%E7%94%A8%E4%B8%83%E7%89%9Bchrome%E6%8F%92%E4%BB%B6%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87/"/>
<id>http://haojen.github.io/2018/03/22/使用七牛chrome插件上传图片/</id>
<published>2018-03-22T15:24:55.000Z</published>
<updated>2018-04-20T15:59:54.000Z</updated>
<content type="html"><![CDATA[<h3 id="下载插件qiniu-upload-files"><a href="#下载插件qiniu-upload-files" class="headerlink" title="下载插件qiniu upload files"></a>下载插件<strong>qiniu upload files</strong></h3><p><img src="http://owrfhrwdi.bkt.clouddn.com/1.png" alt="qiniu upload files"></p><h3 id="打开插件,进行配置"><a href="#打开插件,进行配置" class="headerlink" title="打开插件,进行配置"></a>打开插件,进行配置</h3><h4 id="插件的设置"><a href="#插件的设置" class="headerlink" title="插件的设置"></a>插件的设置</h4><p><img src="http://owrfhrwdi.bkt.clouddn.com/2.png" alt="qiniu upload files"></p><p>分别对应自己的用户中的以下设置。<br><img src="http://owrfhrwdi.bkt.clouddn.com/3.png" alt="qiniu upload files"><br><img src="http://owrfhrwdi.bkt.clouddn.com/4.png" alt="qiniu upload files"></p>]]></content>
<summary type="html">
<h3 id="下载插件qiniu-upload-files"><a href="#下载插件qiniu-upload-files" class="headerlink" title="下载插件qiniu upload files"></a>下载插件<strong>qiniu up
</summary>
</entry>
<entry>
<title>vue状态的不同引用方式引发表单验证</title>
<link href="http://haojen.github.io/2018/03/22/vue%E7%8A%B6%E6%80%81%E7%9A%84%E4%B8%8D%E5%90%8C%E5%BC%95%E7%94%A8%E6%96%B9%E5%BC%8F%E5%BC%95%E5%8F%91%E8%A1%A8%E5%8D%95%E9%AA%8C%E8%AF%81/"/>
<id>http://haojen.github.io/2018/03/22/vue状态的不同引用方式引发表单验证/</id>
<published>2018-03-22T15:15:32.000Z</published>
<updated>2018-04-20T15:59:54.000Z</updated>
<summary type="html">
</summary>
</entry>
<entry>
<title>2个组件之间实现同步Vue</title>
<link href="http://haojen.github.io/2017/11/27/sync-in-components/"/>
<id>http://haojen.github.io/2017/11/27/sync-in-components/</id>
<published>2017-11-27T15:05:40.000Z</published>
<updated>2018-04-20T15:59:54.000Z</updated>
<content type="html"><![CDATA[<p>需求:<strong>组件1</strong>为<strong>组件2</strong>的子组件,<strong>组件1</strong>的A方法需要与<strong>组件2</strong>的B方法同步。<br>使用<strong>$emit</strong>进行通知。在<strong>组件1</strong>中调用<strong>save</strong>方法前,需要接受<strong>组件2</strong>的<strong>beforeSave</strong>方法传回的参数。<br>可以在<strong>组件1</strong>中使用创建<strong>beforeSave</strong>通知组件2执行<strong>beforeSave</strong>方法,然后当<strong>组件2</strong>执行完<strong>beforeSave</strong>之后回调,再使用$emit通知子组件执行<strong>save</strong>方法</p><p>####组件2中的组件1,<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line"><component :ref="id" @beforeSave="beforeSave"> <component></div><div class="line">methods:{</div><div class="line"> beforeSave({entity,formName,isClear}){</div><div class="line"> axios.get('/api/getForeignKey').then(function(resp){</div><div class="line"> let foreignKey = resp.data.foreignKey</div><div class="line"> this.$refs['id'].$emit('save',foreignKey);</div><div class="line"> }).catch(function(error){</div><div class="line"> console.log(error)</div><div class="line"> })</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p><p>####组件1通知组件2<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">beforeSave(entity,formName,isClear){</div><div class="line"> this.$emit('beforeSave',{entity,formName,isClear})</div><div class="line">},</div><div class="line">save(foreignKey){</div><div class="line"> console.log(foreignKey)</div><div class="line">}</div></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<p>需求:<strong>组件1</strong>为<strong>组件2</strong>的子组件,<strong>组件1</strong>的A方法需要与<strong>组件2</strong>的B方法同步。<br>使用<strong>$emit</strong>进行通知。在
</summary>
</entry>
<entry>
<title>使用nexus建立个人npm库</title>
<link href="http://haojen.github.io/2017/11/13/nexus/"/>
<id>http://haojen.github.io/2017/11/13/nexus/</id>
<published>2017-11-13T15:05:04.000Z</published>
<updated>2018-04-20T15:59:54.000Z</updated>
<content type="html"><![CDATA[<p>下面分享一下如何使用nexus建立自己的npm仓库</p><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><hr><ul><li>java环境</li><li>node环境</li><li><a href="https://sonatype-download.global.ssl.fastly.net/nexus/3/nexus-3.6.0-02-win64.zip" target="_blank" rel="external">nexus安装包 3.6.0</a></li></ul><h2 id="运行nexus"><a href="#运行nexus" class="headerlink" title="运行nexus"></a><strong>运行nexus</strong></h2><hr><p>进入解压后nexus的bin文件夹,在此目录打开cmd <strong>(使用gitbash执行可能会有问题)</strong>。执行<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">nexus /run</div></pre></td></tr></table></figure></p><p>默认端口为:<a href="http://localhost:8081/" target="_blank" rel="external">8081</a>,打开可以看到nexus界面了。</p><blockquote><p>点击右上角可以登录,默认账号密码:admin admin123</p></blockquote><p><img src="http://owrfhrwdi.bkt.clouddn.com/W4UKA3OGE%5DNO%5D%60NBDQ5%60DVQ.png" alt="运行成功的图片"></p><blockquote><p>“箱子”图标就是代表着<strong>仓库中的包</strong>,”齿轮”图标则为<strong>设置</strong>,下面我们进入<strong>设置</strong></p></blockquote><p><img src="http://owrfhrwdi.bkt.clouddn.com/TIM%E5%9B%BE%E7%89%8720171114001115.png" alt="界面"></p><blockquote><p>之后,我们将关注<strong>“Repository”</strong>和<strong>“Security”</strong>栏目。分别用于<strong>创建/管理仓库和用户</strong></p></blockquote><h2 id="创建npm需要的Blob存储(此步骤可以忽略)"><a href="#创建npm需要的Blob存储(此步骤可以忽略)" class="headerlink" title="创建npm需要的Blob存储(此步骤可以忽略)"></a>创建npm需要的Blob存储(此步骤可以忽略)</h2><ul><li>分别创建name为”npm-proxy”,”npm-hosted”,”npm-group”的存储(分别用于存放npm代理下载的依赖包、发布的私有依赖包、代理下载的和私有的组合的依赖包)。</li></ul><p><img src="http://owrfhrwdi.bkt.clouddn.com/TIM%E5%9B%BE%E7%89%8720171123001119.png" alt="创建存储1"></p><p><img src="http://owrfhrwdi.bkt.clouddn.com/TIM%E5%9B%BE%E7%89%8720171123001258.png" alt="创建存储2"></p><h2 id="创建npm仓库"><a href="#创建npm仓库" class="headerlink" title="创建npm仓库"></a>创建npm仓库</h2><hr><ul><li>点击<strong>“Create Repository”</strong><br><img src="http://owrfhrwdi.bkt.clouddn.com/TIM%E5%9B%BE%E7%89%8720171114001556.png" alt="Create Repository"></li><li>nexus增加了许多仓库类型,下面我们只关注和<strong>npm</strong>相关的<br><img src="http://owrfhrwdi.bkt.clouddn.com/TIM%E5%9B%BE%E7%89%8720171114001609.png" alt="仓库类型"></li></ul><h3 id="下面说下这几种类型的区别"><a href="#下面说下这几种类型的区别" class="headerlink" title="下面说下这几种类型的区别"></a>下面说下这几种类型的区别</h3><ul><li><strong>hosted</strong> 为私有的仓库,我们在本地写好的npm插件就是发布到这个地方的。这个就是我们搭建私有仓库的目的。</li><li><strong>proxy</strong> 为代理的镜像地址(我们一般设置为淘宝镜像即可),大概可以理解为,nexus帮我们从这个地址下载其他的npm依赖包。而且会自动缓存到nexus仓库。</li><li><strong>group</strong> 用于私有仓库和代理仓库的组合。就是我们可以从<strong>group</strong>下载到私有的依赖(存放在nexus仓库的)和npm官网的依赖。<blockquote><p>需要注意的是,<strong>hosted</strong>仅用于发布你的私有依赖,所以,如果你从<strong>hosted</strong>下载依赖是无法下载的。下载只能通过<strong>group</strong>下载。</p></blockquote></li></ul><h3 id="下面开始建立仓库"><a href="#下面开始建立仓库" class="headerlink" title="下面开始建立仓库"></a>下面开始建立仓库</h3><ol><li><p>创建代理仓库(npm-proxy)<br><img src="http://owrfhrwdi.bkt.clouddn.com/TIM%E5%9B%BE%E7%89%8720171123001544.png" alt="代理仓库"></p><blockquote><ul><li>name为<strong>“npm-proxy”</strong></li><li>remote storage为<strong>“<a href="https://registry.npm.taobao.org" target="_blank" rel="external">https://registry.npm.taobao.org</a>“</strong></li><li>存储为<strong>“npm-proxy”</strong></li></ul></blockquote></li><li><p>创建私有仓库(npm-hosted)<br><img src="http://owrfhrwdi.bkt.clouddn.com/TIM%E5%9B%BE%E7%89%8720171123001613.png" alt="私有类型"></p><blockquote><ul><li>name为<strong>“npm-hosted”</strong></li><li>存储为<strong>“npm-hosted”</strong></li></ul></blockquote></li><li><p>创建组个仓库(npm-group)<br><img src="http://owrfhrwdi.bkt.clouddn.com/TIM%E5%9B%BE%E7%89%8720171123001749.png" alt="私有类型"></p><blockquote><ul><li>name为<strong>“npm-group”</strong></li><li>存储为<strong>“npm-group”</strong></li><li>然后在group中,把前面2个创建的拖到右边框中</li></ul></blockquote></li></ol><p>以上,仓库已经创建完成。可以通过界面进入仓库,查看刚刚创建的仓库。也可以直接访问,如果出现404,则说明name写错咯。地址和name对应的</p><ul><li><a href="http://localhost:8081/repository/npm-proxy/" target="_blank" rel="external">http://localhost:8081/repository/npm-proxy/</a></li><li><a href="http://localhost:8081/repository/npm-hosted/" target="_blank" rel="external">http://localhost:8081/repository/npm-hosted/</a></li><li><a href="http://localhost:8081/repository/npm-group/" target="_blank" rel="external">http://localhost:8081/repository/npm-group/</a></li></ul><h3 id="创建用户"><a href="#创建用户" class="headerlink" title="创建用户"></a>创建用户</h3><blockquote><p>之后我们发布需要这个用户登录</p></blockquote><p><img src="http://owrfhrwdi.bkt.clouddn.com/U4WTM%25W%7BSWM68C3IFF%7DF%60QP.png" alt="创建用户"><br>同时把<strong>npm Bearer Token Realm</strong>置于active<br><img src="http://owrfhrwdi.bkt.clouddn.com/M_6BNS%60OHOFCU_HSUURX%28W0.png" alt="创建用户"></p><h2 id="测试下载依赖包"><a href="#测试下载依赖包" class="headerlink" title="测试下载依赖包"></a>测试下载依赖包</h2><ol><li><p>切换npm的registry。可以运行一下命令。记住是<strong>npm-group</strong> 这个地址。</p><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">npm config set registry http://localhost:8081/repository/npm-group/</div></pre></td></tr></table></figure><p>同样的,我们也可以打开一下这个文件修改设置</p><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">C:\Users\你的用户名\.npmrc</div></pre></td></tr></table></figure><p>推荐设置(<strong>可以解决phantomjs、chromedriver、node-sass无法下载的问题</strong>)。直接把一下拷贝进.npmrc文件即可</p><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">loglevel=info</div><div class="line">scripts-prepend-node-path=true</div><div class="line">registry=http://localhost:8081/repository/npm-group/</div><div class="line">chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver</div><div class="line">phantomjs_cdnurl=http://cnpmjs.org/downloads</div><div class="line">sass_binary_site=https://npm.taobao.org/mirrors/node-sass/</div></pre></td></tr></table></figure></li><li><p>设置完之后,我们可以随便下载一个依赖,看是否是经过nexus下载的。</p><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">npm install -g generator-vuejs</div></pre></td></tr></table></figure><p>可以看到的确是走npm-group仓库的。<br><img src="http://owrfhrwdi.bkt.clouddn.com/VZWA5%25L9U2%250X%29I$1%7BV%5DHSL.png" alt="测试"><br>这时候去nexus库查看,可以看到,nexus把从淘宝下载的镜像都缓存在本地了。<br><img src="http://owrfhrwdi.bkt.clouddn.com/4RVO~K5PROHTXU%7B$125@_YE.png" alt="缓存"></p></li></ol><h2 id="测试发布"><a href="#测试发布" class="headerlink" title="测试发布"></a>测试发布</h2><ol><li><p>切换成<strong>npm-hosted</strong> 的地址</p><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">npm config set registry http://localhost:8081/repository/npm-hosted</div></pre></td></tr></table></figure></li><li><p>登录,运行以下命令,然后输入刚刚创建的用户名和密码即可</p><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">npm adduser</div></pre></td></tr></table></figure><p><img src="http://owrfhrwdi.bkt.clouddn.com/TSK0$V7J3H_F_L6LBO32YLL.png" alt="登录"></p></li><li><p>找一个需要发布的依赖,在根目录运行以下命令,设置registry为npm-hosted,并发布</p><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">npm publish</div></pre></td></tr></table></figure><p>200即为发布成功<br><img src="http://owrfhrwdi.bkt.clouddn.com/MUYXX3X%5B9JMD4F$~EM4P%28$1.png" alt="登录"><br>去nexus仓库可以看到刚刚发布的依赖包<br><img src="http://owrfhrwdi.bkt.clouddn.com/N%5DT%29Q4$%7B%5DZ0%28WF%28%25OE%7BR%257U.png" alt="登录"></p></li></ol>]]></content>
<summary type="html">
<p>下面分享一下如何使用nexus建立自己的npm仓库</p>
<h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><hr>
<ul>
<li>java环境</li>
<li>no
</summary>
</entry>
<entry>
<title>用状态驱动应用</title>
<link href="http://haojen.github.io/2017/10/28/state-of-vue/"/>
<id>http://haojen.github.io/2017/10/28/state-of-vue/</id>
<published>2017-10-28T15:27:08.000Z</published>
<updated>2018-04-20T15:59:54.000Z</updated>
<content type="html"><![CDATA[<h2 id="状态的必要性"><a href="#状态的必要性" class="headerlink" title="状态的必要性"></a>状态的必要性</h2><hr><p>当组件A逐渐变得庞大,需要从组件A中抽取模块变成组件B,或者需要引入更多的组件时,如果通过props来进行组件之间的通信,那么会变得困难,特别是需要依赖更多其他组件的属性时,而且此时,组件间的耦合度会变大,而且对于通信内容都是单向的(通过on可以实现双向,但是比较麻烦)。这时候,组件间的通信都使用状态来管理,那么可以降低耦合度,而且能够响应,并实时更新视图。</p>]]></content>
<summary type="html">
<h2 id="状态的必要性"><a href="#状态的必要性" class="headerlink" title="状态的必要性"></a>状态的必要性</h2><hr>
<p>当组件A逐渐变得庞大,需要从组件A中抽取模块变成组件B,或者需要引入更多的组件时,如果通过prop
</summary>
</entry>
<entry>
<title>使用vue开发如何解决跨域以及验证问题</title>
<link href="http://haojen.github.io/2017/09/29/CROS/"/>
<id>http://haojen.github.io/2017/09/29/CROS/</id>
<published>2017-09-29T15:29:11.000Z</published>
<updated>2018-06-30T04:16:10.000Z</updated>
<content type="html"><![CDATA[<p>开代理就可以了。</p>]]></content>
<summary type="html">
<p>开代理就可以了。</p>
</summary>
</entry>
<entry>
<title>Java开发者常用工具</title>
<link href="http://haojen.github.io/2017/09/23/java-developer-kit/"/>
<id>http://haojen.github.io/2017/09/23/java-developer-kit/</id>
<published>2017-09-23T15:29:44.000Z</published>
<updated>2018-04-20T15:59:54.000Z</updated>
<content type="html"><![CDATA[<p>重装系统是一件非常麻烦的事情,特别是继续再次搭建环境,每次需要用到的时候才会想到:“oh!我需要这个工具!”。下面给大家汇总一下一个java程序员所需要的一些工具,以备不时之需:</p><h2 id="环境篇"><a href="#环境篇" class="headerlink" title="环境篇"></a>环境篇</h2><hr><h3 id="Java环境"><a href="#Java环境" class="headerlink" title="Java环境"></a>Java环境</h3><p>官网地址,截止2017年9月25日 最新的版本(登录后下载):</p><ul><li><a href="http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase5-419410.html" target="_blank" rel="external">jdk-5u22</a></li><li><a href="http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase6-419409.html" target="_blank" rel="external">jdk-6u45</a></li><li><a href="http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase7-521261.html" target="_blank" rel="external">jdk-7u80</a></li><li><a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html" target="_blank" rel="external">jdk-8u144</a></li></ul><p>为了方便使用windows的程序员快速切换各个版本的JDK,JDK6~8的exe都做成了zip并上传到百度云,这个可以直接修改环境变量就可以快速切换了:<br><a href="https://pan.baidu.com/s/1pKItryr" target="_blank" rel="external">百度云地址</a><br>提取密码:shvy</p><h3 id="Tomcat"><a href="#Tomcat" class="headerlink" title="Tomcat"></a>Tomcat</h3><p>包含以下版本</p><ul><li>tomcat-7.0.82</li><li>tomcat-8.5.23</li><li>tomcat-9.0.1(beta)</li></ul><p><a href="https://pan.baidu.com/s/1pKJaXXT" target="_blank" rel="external">百度云地址</a><br>提取密码:m3d3</p>]]></content>
<summary type="html">
<p>重装系统是一件非常麻烦的事情,特别是继续再次搭建环境,每次需要用到的时候才会想到:“oh!我需要这个工具!”。下面给大家汇总一下一个java程序员所需要的一些工具,以备不时之需:</p>
<h2 id="环境篇"><a href="#环境篇" class="headerli
</summary>
</entry>
</feed>