Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
要: 在WebGIS的瀏覽器端存在繪圖效率差、不能直接支持矢量繪圖等問題。為提高客戶端的交互性和實時性,在解決瀏覽器不支持矢量繪圖和渲染速度慢、存儲空間小、傳輸速率慢這些問題的基礎上,結合HTML5中的Canvas、WebSocket、WebStorage技術,構建了WebGIS實時客戶端,有效地改善了客戶端存在的問題,改善用戶的體驗。
0 引言
WebGIS是GIS技術與Internet的結合體,是對網絡GIS的發展,它將GIS從一種使用計算機的處理地理信息的系統工具,變為一種網絡共享資源,提高了地理信息的使用效率,使地理信息的價值得以充分體現[1]。WebGIS的實現手段主要是基于Web技術的多級B/S體系結構,即瀏覽器、GIS服務器、數據庫等。B/S模式的構架簡化了客戶端系統的部署,降低了用戶使用難度,同時也極大提高了系統的可維護性[2]。但是這種被動的工作模式無法滿足用戶實時性的需求。對于WebGIS的架構研究,以前主要是對服務器端技術的改進,如使用CGI、Server API等服務端技術,但是這些技術對于服務器及網絡的要求較高。隨著客戶端技術的發展,Java Applet技術、Plug-in技術、Ajax技術的出現擴展了客戶端的功能,但是用戶需要預先安裝這些插件,安裝插件帶來了一定的安全隱患和不方便性。對比這兩種形式,使用HTML5的新技術實現的功能并不需要插件支持,且其本地存儲功能和高效率的雙向通信功能,還有動態快速繪圖功能的提出,使實時客戶端的實現成為可能。
1 實時客戶端的WebGIS系統結構
HTML5是W3C推出的新標準,其強大功能已經被大部分的瀏覽器支持,同時,相對于以前的版本,HTML5的改變不僅僅是使用更方便。第一,它新增了更具有語義化的標簽和使用更智能化的表單;第二,HTML5還新增了許多JavaScript API,如實時繪圖(Canvas和SVG)、離線存儲(WebStorage)、實時通信(WebSocket)API等,這些API為實現實時客戶端提供了可能。用HTML5來實現WebGIS有地圖無限縮放而圖不失真,地圖的顯示渲染效果逼真的優勢;且支持JavaScript腳本實現地圖的漫游、縮放、查詢等功能,這些功能都無需插件支持并可在不同平臺與設備上運行[3]。根據這些特性,本文在傳統架構的基礎上,構建了圖1所示的WebGIS實時客戶端。
在客戶端這些模塊中使用HTML5和JavaScript技術,實現數據地圖的繪制、本地存儲、數據傳輸等功能,將部分簡單的功能交給客戶端完成,增加了WebGIS客戶端的交互能力,減少了服務器的傳輸壓力,也增加了數據傳輸的效率,實現了客戶端的實時性。
2 WebGIS客戶端的具體設計
2.1 數據實時更新與傳輸設計
空間數據格式有柵格數據和矢量數據。柵格數據交互性能差,可用來展示空間數據,矢量數據交互性較好,可用來表示空間對象,但是客戶端不能直接支持矢量數據的二進制格式傳輸,所以數據在傳輸中就要進行格式編碼,目前使用的比較多的數據傳輸格式是GeoJSON(基于JSON數據格式的地理要素表示格式)。JSON(JavaScript Object Notation)是輕量級數據交換格式,適合于服務器與瀏覽器(通過JavaScript)交互[4],在瀏覽器端JSON能夠簡單快速地解析成可以被客戶端操作的JavaScript地理信息,不需要使用專門的文本解析API進行操作。空間數據傳輸大多使用Ajax的異步傳輸方式,但Ajax輪詢方式的時延較長,傳輸的實時性不高,因此將Ajax用于地圖數據的推送。實時性方面還是需要HTML5的WebSocket API實現。WebSocket使瀏覽器具有客戶機/服務器(C/S)模式下應用程序的實時通信能力[5]。WebSocket的優勢有:(1)為瀏覽器和服務器之間建立的更高效的雙向通信提供支持。其連接本質為TCP連接,因此瀏覽器通過JavaScript向服務器發出建立WebSocket連接的請求,onopen事件接收消息,連接建立以后,客戶端和服務器端就可通過TCP連接直接交換數據。(2)WebSocket有更為輕量級的Header,除了首次建立鏈接時需要發送頭部與普通Web鏈接類似的數據之外,連接建立后,相互溝通的Header就會很簡潔,大大減少了冗余的數據傳輸[6];通過新建WebSocket實例建立握手并完成與服務器的連接,建立好連接之后數據就可以以全雙工模式在客戶端與服務器之間進行雙向傳輸,并一直保持連接,直到用戶主動關閉[3]。圖2是傳統傳輸方式與WebSocket傳輸方式數據量的對比,從結果可以看出,當傳輸數據量增大時,WebSocket的效率更高。
需要在服務器端安裝開源的WebSocket支持數據庫,如Node.js、LibWebSockets、PHP WebSocket Server等,以調用接口使用。具體傳輸過程是:GIS服務器從空間數據庫獲取數據,將空間數據解析成JSON的格式,然后發送到已經與WebSocket服務器連接的客戶端,客戶端WebSocket實例的onmessage事件接收數據并使用JSON.parse函數將JSON字符串解析成JavaScript對象,再根據對象的內容在WebGIS的地圖中解析顯示。WebSocket API一個顯著特點是,連接建立后,服務器可主動推送消息。支持WebSocket協議的服務端接受請求和處理WebSocket任務,在客戶端可用WebStorage存儲模塊緩存傳輸過來的數據,WebSocket的中間傳輸機制就實現了數據實時更新。
2.2 客戶端空間數據緩存設計
客戶端緩存功能主要是由WebStorage API來實現,WebStorage API是以Key-Value形式來進行數據的持久性存儲。傳統客戶端一般是使用Cookie存儲數據,但是它效率低,存儲空間小,不能滿足大量矢量數據的存儲。WebStorage提供的兩種存儲方式可以改善這個狀況,一種是SessionStorage,它是一種會話級別的存儲方式,存儲的數據只在當前頁面有效,當頁面關閉時,數據也會隨之刪除,據此SessionStorage可以用在矢量圖繪制的緩存方面,即讓SessionStorage自動緩存解析好的JSON格式的矢量層數據,當需要數據時直接從SessionStorage中提取JSON數據,這比從空間數據庫中獲取再解析效率明顯更高,數據顯示模塊可以直接從中獲取數據進行繪制。另一種方式是LocalStorage,它是一個跨多窗口且數據永久存儲的方式,只有使用清除函數clear、removeItem或手動刪除數據時數據才會從瀏覽器中清除,同時它的數據可以在同源的窗口或標簽共享使用。因此它可以用來永久存儲空間分析后的數據或服務器發送的數據和用戶數據,下次用戶打開瀏覽器可直接使用這些數據。圖3是具體矢量數據本地存儲過程。將數據緩存到本地,不用與服務器發生交互,客戶端存儲的數據可以由JavaScript訪問。
WebStorage存儲技術和WebSocket技術可結合使用并與JavaScript一起實現數據的實時更新,減輕服務器壓力。用戶發送數據請求后,WebSocket建立連接,將得到的數據解析后存儲在WebStorage預先定義好的空間中,等待用戶提取。對于常須更新地圖數據的操作采用這種預先存儲的方式,可以加快數據的渲染效率。為了提高圖3的實時更新效果,可以設定異步存儲機制,過程如下:(1)創建并初始化WebStorage對象,設置緩存區大小(緩存區分段);(2)用戶發出消息,觸發onopen事件;(3)為WebSocket對象的信息添加偵聽器;(4)服務器調用received函數處理事件;(5)客戶端接收服務器發送的消息,觸發緩存判斷函數,判斷緩存大小,如果超出,設置緩存片段的編號,對象異步sends數據請求服務器處理;(6)服務器將片段編號入隊(服務端設置),直到傳輸完成,清除編號。這種傳輸方式將進一步減少網絡流量,減少服務器的負載,提升傳輸效率。
2.3 數據顯示設計
HTML5現提供了Canvas API,它可以解決傳統開發瀏覽器支持度差、跨平臺性不強和繪制矢量圖形需要插件的問題,通過JavaScript在瀏覽器不依賴任何插件的情況下高效地繪制動態圖形[7],避免了安裝插件帶來安全風險。
2.3.1 繪制方法
Canvas API使用比較簡單,像其他HTML標簽一樣,只需在HTML5的頁面中添加一個<canvas>元素即可。Canvas繪圖首先要獲得上下文(context),因為Canvas自己本身并沒有繪圖能力,所以所有的繪圖工作要由JavaScript完成。它的工作過程為:先定義Canvas元素的id,然后通過getElementById函數找到自己前面創建好的Canvas元素,最后用JavaScript調用繪圖API接口得到上下文繪圖環境后就可在畫布上繪制任何的圖形了。但Canvas只支持一種基本圖形——矩形,想使用Canvas繪制其他的圖形,就要使用其提供的路徑(Path)繪制函數[8],使用beginPath開始繪制,使用moveTo、lineTo繪制直線,繪制完畢后調用fill、stroke進行填充或者設置邊框,最后調用closePath結束圖形繪制。Canvas在矢量數據方面是像素級管理,Canvas的路徑操作能充分滿足矢量數據中的點要素、線要素、面要素以及符號的表達要求。
2.3.2 數據顯示過程
用Canvas與JavaScript技術實現地圖實時繪制。地理實體對象可以根據OGC的簡單要素規范和GIS界的研究將其分為:點狀實體、線狀實體、面狀實體、標注實體和柵格實體[3]。Canvas可直接使用這些實體,對于柵格實體,可以用JavaScript對象表示,通過API drawImage直接在HTML5 Canvas中繪制。矢量實體的地理要素從GeoJSON文本轉化為JavaScript對象,根據該對象的信息,調用坐標轉換對象,將坐標轉換成Canvas元素里的屏幕坐標來對應顯示要素。實現實時繪圖的流程為:(1)服務器從數據庫獲取數據;(2)數據進行JSON格式解析;(3)瀏覽器加載地圖,調用Canvas畫布及函數實現繪圖和地圖的顯示;(4)地圖操作由自定義腳本實現地圖渲染。Canvas在客戶端展現地理數據的靈活性與互操作性要優于傳統的切片技術,并且在地圖加載速度方面有明顯的優勢[8],因此將Canvas和WebStorage結合起來,可以提高實時性能,將要顯示或者要存儲的數據先經過緩存,再進行顯示或存儲,這種機制效率明顯更高。圖4說明了從數據推送到顯示的流程。
3 客戶端整體過程
Canvas實現實時繪圖和快速渲染,WebSocket API在通信方面提供了支持。WebStorage提供了客戶端的本地存儲技術,以地圖放大操作為例,用戶提交請求,數據獲取函數可以從SessionStorage中獲取數據,然后將緩存的數據轉換成JavaScript對象,最后通過Canvas直接添加在地圖中,同時,緩存中的數據不斷更新。WebSocket的雙向通信機制和WebStorage的異步存儲機制加速了數據交換效率,空間數據庫也通過WebGIS服務器,在實時通信的基礎上,將數據以JSON文本格式傳輸到客戶端,存入SessionStorage中,窗口關閉后,所有數據存入LocalStorage,供用戶下次直接使用。這種方式的效率很明顯會比從服務器獲取數據的方式高,實時性要好,如需要執行其他的交互操作,也可以基于這種方式實現。
4 結論
隨著Web技術的發展,客戶端的交互性和實時性要求不斷提升,據此,本文將HTML5的新特性與JavaScript技術結合,在WebSocket雙向通信機制和WebStorage緩存機制實現異步存儲提供的數據支撐,Canvas能實現動態繪圖和快速渲染的基礎上,提出了一種實時性更強的WebGIS客戶端,為建立實時的WebGIS客戶端提供了一種方案。HTML5中的新技術雖然強大,還是有需要加強的地方,WebStorage讓數據能夠緩存在本地,但是由于是存儲在本地,數據容易泄漏,安全性還有欠缺。未來WebGIS的發展會隨著數據量的增大實現云平臺化,資源更龐大,數據更易共享,用戶使用起來也會更方便。
參考文獻
[1] 孟令奎,史文中,張鵬林,等.網絡地理信息系統原理與技術[M].北京:科學出版社,2010.
[2] 李博霏,李欣,李艷明.基于瀏覽器的地理信息服務客戶端技術研究[J].計算機工程與設計,2011(9):3031-3035.
[3] 龍云.基于HTML5的WebGIS研究[D].贛州:江西理工大學,2013.
[4] CROCKFORD D. The application/json media type for JavaScript Object Notation(JSON)[EB/OL]. [2006-07]. http://tools.ietf.org/html/rfc4627.
[5] 徐卓揆.基于HTML5、Ajax和Web Service的WebGIS研究[J].測繪科學,2012,37(1):145-147.
[6] 魏進鋒,孫春華.應用HTML5的WebSocket實現BiDirection數據交換[EB/OL].[2012-12-28](2015-02-25).http://www.ibm.com/developerworks/cn/web/1112_weijf_websocket/.
[7] 王曉.基于HTML5的矢量地圖發布關鍵技術研究[D].南京:南京師范大學,2011.
[8] 梁春雨,李新通.使用HTML5 Canvas構建基于GeoJSON的輕量級WebGIS[J].計算機科學與應用,2012(2):189-196.
擊查看智能機器人動圖
javascript課題:Web前端開發人工智能機器人
知識點: ajax概念解析,ajax封裝,如何調用數據庫
函數封裝,javascript正則匹配,元素創建,企業開發標準
2017就業形勢分析,面試技巧等
PS:現在人工智能很火,包括前端時間,騰訊的群里面都有了官方的機器人了,當然是為了活躍群氣氛,也成了很多宅男的解悶的對象。我們今天的課題就是在自己的網站上搭建一個智能機器人的聊天窗口,當然數據不是我們自己編輯的,是從其他地方調用的,但是這樣的一個項目也比較考驗我們的前端知識的綜合能力,特別是對于javascript的使用,包括ajax的封裝等等,如果你的個人博客上也能有這樣的一個人工機器人,我相信對于web前端的求職會有很大的幫助的!
如果想要更多的企業求職加分項目,案例,可以來一下我的前端群216634437,每天都會精挑細選一個特效,項目出來詳細講解,分享!
需要文檔版源碼來我的前端群216634437,已上傳到群文件
智能機器人學習視頻:HTML5+javascript大神帶你開發人工智能機器人
頭條號里有許多web前端學習視頻,企業常用特效/案例/項目,敬請關注!
看完這張圖有多少想去@baby Q的?
Django4.1環境和python3語言版本和html5語言和CSS3語言,重點參考github開源內容和Stackoverflow 的帖子內容,開發一個安全的web網站。請重點講解下擴展auth_user表的方式和代碼,擴展字段為單位名稱、部門名稱、小組名稱、移動電話號碼,其中擴展字段用戶只能選擇數據庫中已有的單位名稱、部門名稱、小組名稱,并且單位名稱、部門名稱、小組名稱三個字段只有管理員可以在頁面修改,請使用繼承AbstractUser類的方式,不要使用profile方式,并且單位名稱、部門名稱、小組名稱三個字段可以在頁面單獨修改,并在代碼中添加注釋內容,解釋每一行代碼的作用。
首先,我們需要在models.py中定義一個新的類來擴展AbstractUser類:
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
# 添加新的字段
unit_name = models.CharField(max_length=100, null=True, blank=True)
department_name = models.CharField(max_length=100, null=True, blank=True)
group_name = models.CharField(max_length=100, null=True, blank=True)
mobile_number = models.CharField(max_length=20, null=True, blank=True)
在這個新的CustomUser類中,我們添加了4個新的字段(unitname、departmentname、groupname和mobilenumber)來擴展AbstractUser類。這些新字段的意義分別是單位名稱、部門名稱、小組名稱和移動電話號碼。
接下來,我們需要創建一個新的表單類來在網站的頁面上顯示這些新的字段并且實現管理員可以修改這些字段的功能。這里我們將使用Django的ModelForm來簡化表單的創建過程,同時也可以保證表單的安全性。
from django import forms
from .models import CustomUser
class CustomUserForm(forms.ModelForm):
# 定義表單中的字段
unit_name = forms.CharField(max_length=100, required=False)
department_name = forms.CharField(max_length=100, required=False)
group_name = forms.CharField(max_length=100, required=False)
mobile_number = forms.CharField(max_length=20, required=False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 設置單位名稱、部門名稱、小組名稱三個字段只能選擇數據庫中已有的名稱
self.fields['unit_name'].widget.attrs['readonly'] = True
self.fields['department_name'].widget.attrs['readonly'] = True
self.fields['group_name'].widget.attrs['readonly'] = True
self.fields['unit_name'].choices = self.get_unit_name_choices()
self.fields['department_name'].choices = self.get_department_name_choices()
self.fields['group_name'].choices = self.get_group_name_choices()
# 獲取單位名稱、部門名稱、小組名稱的選項列表
def get_unit_name_choices(self):
# 從數據庫中獲取已有的單位名稱列表
return [(unit_name, unit_name) for unit_name in CustomUser.objects.values_list('unit_name', flat=True).distinct()]
def get_department_name_choices(self):
# 從數據庫中獲取已有的部門名稱列表
return [(department_name, department_name) for department_name in CustomUser.objects.values_list('department_name', flat=True).distinct()]
def get_group_name_choices(self):
# 從數據庫中獲取已有的小組名稱列表
return [(group_name, group_name) for group_name in CustomUser.objects.values_list('group_name', flat=True).distinct()]
# 定義表單的Meta類
class Meta:
model = CustomUser
fields = ('username', 'email', 'first_name', 'last_name', 'unit_name', 'department_name', 'group_name', 'mobile_number')
在這個新的CustomUserForm表單類中,我們定義了4個字段(unitname、departmentname、groupname和mobilenumber),并且通過重載init方法來確保這些字段只能選擇數據庫中已有的名稱。同時,我們還定義了一個Meta類來指定表單對應的模型類和需要顯示的字段。
接下來,我們需要在網站的視圖函數中使用這個CustomUserForm類來實現修改用戶信息的功能。這里我們將使用Django的generic view來簡化視圖函數的創建過程。
from django.shortcuts import render, redirect
from django.views.generic.edit import UpdateView
from django.urls import reverse_lazy
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from .models import CustomUser
from .forms import CustomUserForm
@method_decorator(login_required, name='dispatch')
class CustomUserUpdateView(UpdateView):
model = CustomUser
form_class = CustomUserForm
template_name = 'user_update.html'
success_url = reverse_lazy('user_update')
# 重載get_object方法以確保只有管理員可以訪問該頁面
def get_object(self, queryset=None):
obj = super().get_object(queryset=queryset)
if not self.request.user.is_staff:
# 如果當前用戶不是管理員,則重定向到用戶詳情頁面
return redirect('user_detail', pk=obj.pk)
return obj
在這個新的CustomUserUpdateView類中,我們使用了Django的UpdateView來處理用戶信息的修改請求。我們指定了需要修改的模型類(CustomUser)、使用的表單類(CustomUserForm)、模板名稱(userupdate.html)以及修改成功后重定向的URL地址(userupdate)。同時,我們還通過重載get_object方法來確保只有管理員可以訪問該頁面。
最后,我們需要在網站的urls.py文件中添加一個新的URL路由來將用戶信息修改頁面映射到CustomUserUpdateView視圖類。
from django.urls import path
from .views import CustomUserUpdateView
urlpatterns = [
path('user/update/', CustomUserUpdateView.as_view(), name='user_update'),
# 其他URL路由...
]
這樣,我們就完成了擴展authuser表的方式和代碼。在這個新的CustomUser類中,我們添加了4個新的字段(unitname、departmentname、groupname和mobile_number)來擴展AbstractUser類。同時,我們使用了CustomUserForm類來創建一個表單來顯示和修改這些新的字段,并使用了CustomUserUpdateView類來處理這個表單的提交。在這個過程中,我們也注意到了安全性的問題,并確保只有管理員可以訪問用戶信息修改頁面,并限制了用戶可以選擇的單位名稱、部門名稱和小組名稱的范圍。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。