我是Javascript的新手,因此需要JS - 我现在正在教自己使用Openlayers 3的例子,其中,我刚刚附加到一个大的JS文件中。看到这种情况很快变得难以驾驭,我读到了有关RequireJS的内容,并认为我应该养成从一开始就做好事情的习惯; “这就是我遇到问题的地方。”
[不是我认为这很重要,但我使用的是Asp.net MVC] 基本上,我希望将文件分解为更小的相关模块,例如
...可以灵活地一次激活所有图层,或者选择一些易于管理的JS代码。
我已经多次尝试将这些代码分解为这些单独的JS文件,[map / draw / Geolocation]并且都失败了,因为我觉得我没有理解requireJS方法(以免混淆读者而我自己,我忽略了添加我的尝试)。
以下是有效的基本代码:
require.config({
baseUrl: "/Scripts",
paths: {
//jquery: "/lib/jquery-1.11.1.min",
ol: [
"http://openlayers.org/en/v3.8.1/build/ol",
"/lib/ol"
],
domReady: "/lib/domReady"
},
//map: { main: { test: "/Modules/Test/scripts/test" } },
//The shim section is to tell RequireJS about any dependencies your files have before they can be used.
//Here, we are saying if we call “ol” to load that module, we have to load “jquery” first.
//shim: {
//ol: ["jquery"]
//},
//packages: [
// {
//name: 'test',
//location: 'http://...
//main: 'main'
//}]
});
文件我希望分手:
define(["ol"], function (ol) {
$(document).ready(function () {
//****************
//------MAP-------
//Setup Map Base
// creating the view
var view = new ol.View({
center: ol.proj.fromLonLat([5.8713, 45.6452]),
zoom: 19
});
// creating the map
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: "map",
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
view: view
});
//****************
//-----DRAW------
var features = new ol.Collection();
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector({ features: features }),
style: new ol.style.Style({
fill: new ol.style.Fill({
color: "rgba(255, 255, 255, 0.2)"
}),
stroke: new ol.style.Stroke({
color: "#ffcc33",
width: 2
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: "#ffcc33"
})
})
})
});
featureOverlay.setMap(map);
var modify = new ol.interaction.Modify({
features: features,
// the SHIFT key must be pressed to delete vertices, so
// that new vertices can be drawn at the same position
// of existing vertices
deleteCondition: function (event) {
return ol.events.condition.shiftKeyOnly(event) &&
ol.events.condition.singleClick(event);
}
});
map.addInteraction(modify);
var draw; // global so we can remove it later
function addInteraction() {
draw = new ol.interaction.Draw({
features: features,
type: /** @type {ol.geom.GeometryType} */ (typeSelect.value)
});
map.addInteraction(draw);
}
var typeSelect = document.getElementById("type");
/**
* Let user change the geometry type.
* @param {Event} e Change event.
*/
typeSelect.onchange = function (e) {
map.removeInteraction(draw);
addInteraction();
};
addInteraction();
//****************
//---GEOLOCATION---//
// Common app code run on every page can go here
// Geolocation marker
var markerEl = document.getElementById("geolocation_marker");
var marker = new ol.Overlay({
positioning: "center-center",
element: markerEl,
stopEvent: false
});
map.addOverlay(marker);
// LineString to store the different geolocation positions. This LineString
// is time aware.
// The Z dimension is actually used to store the rotation (heading).
var positions = new ol.geom.LineString([],
/** @type {ol.geom.GeometryLayout} */ ("XYZM"));
// Geolocation Control
var geolocation = new ol.Geolocation( /** @type {olx.GeolocationOptions} */({
projection: view.getProjection(),
trackingOptions: {
maximumAge: 10000,
enableHighAccuracy: true,
timeout: 600000
}
}));
var deltaMean = 500; // the geolocation sampling period mean in ms
// Listen to position changes
geolocation.on("change", function (evt) {
var position = geolocation.getPosition();
var accuracy = geolocation.getAccuracy();
var heading = geolocation.getHeading() || 0;
var speed = geolocation.getSpeed() || 0;
var m = Date.now();
addPosition(position, heading, m, speed);
var coords = positions.getCoordinates();
var len = coords.length;
if (len >= 2) {
deltaMean = (coords[len - 1][3] - coords[0][3]) / (len - 1);
}
var html = [
"Position: " + position[0].toFixed(2) + ", " + position[1].toFixed(2),
"Accuracy: " + accuracy,
"Heading: " + Math.round(radToDeg(heading)) + "°",
"Speed: " + (speed * 3.6).toFixed(1) + " km/h",
"Delta: " + Math.round(deltaMean) + "ms"
].join("<br />");
document.getElementById("info").innerHTML = html;
});
geolocation.on("error", function () {
alert("geolocation error");
// FIXME we should remove the coordinates in positions
});
// convert radians to degrees
function radToDeg(rad) {
return rad * 360 / (Math.PI * 2);
}
// convert degrees to radians
function degToRad(deg) {
return deg * Math.PI * 2 / 360;
}
// modulo for negative values
function mod(n) {
return ((n % (2 * Math.PI)) + (2 * Math.PI)) % (2 * Math.PI);
}
function addPosition(position, heading, m, speed) {
var x = position[0];
var y = position[1];
var fCoords = positions.getCoordinates();
var previous = fCoords[fCoords.length - 1];
var prevHeading = previous && previous[2];
if (prevHeading) {
var headingDiff = heading - mod(prevHeading);
// force the rotation change to be less than 180°
if (Math.abs(headingDiff) > Math.PI) {
var sign = (headingDiff >= 0) ? 1 : -1;
headingDiff = -sign * (2 * Math.PI - Math.abs(headingDiff));
}
heading = prevHeading + headingDiff;
}
positions.appendCoordinate([x, y, heading, m]);
// only keep the 20 last coordinates
positions.setCoordinates(positions.getCoordinates().slice(-20));
// FIXME use speed instead
if (heading && speed) {
markerEl.src = "/OrchardLocal/Media/Default/Map/geolocation_marker.png"; //"data/geolocation_marker_heading.png";F:\DeleteMeThree\_Orchard-19x\src\Orchard.Web\Modules\Cns.OL\Contents/Images/geolocation_marker.png
} else {
//alert(markerEl.src); PETE: Not sure if this is std OL practice, but this is achieved by already having an element
//called "geolocation_marker" in the dom as an img, which this uses? Strange to me
markerEl.src = "/OrchardLocal/Media/Default/Map/geolocation_marker.png"; //I added img via media module - ridiculous?!
}
}
var previousM = 0;
// change center and rotation before render
map.beforeRender(function (map, frameState) {
if (frameState !== null) {
// use sampling period to get a smooth transition
var m = frameState.time - deltaMean * 1.5;
m = Math.max(m, previousM);
previousM = m;
// interpolate position along positions LineString
var c = positions.getCoordinateAtM(m, true);
var view = frameState.viewState;
if (c) {
view.center = getCenterWithHeading(c, -c[2], view.resolution);
view.rotation = -c[2];
marker.setPosition(c);
}
}
return true; // Force animation to continue
});
// recenters the view by putting the given coordinates at 3/4 from the top or
// the screen
function getCenterWithHeading(position, rotation, resolution) {
var size = map.getSize();
var height = size[1];
return [
position[0] - Math.sin(rotation) * height * resolution * 1 / 4,
position[1] + Math.cos(rotation) * height * resolution * 1 / 4
];
}
// postcompose callback
function render() {
map.render();
}
//EMP
//$("#geolocate").click(function () {
// alert("JQuery Running!");
//});
// geolocate device
var geolocateBtn = document.getElementById("geolocate");
geolocateBtn.addEventListener("click", function () {
geolocation.setTracking(true); // Start position tracking
map.on("postcompose", render);
map.render();
disableButtons();
}, false);
});
})
考虑到我将来会有更多的模块要附加,使用RequireJS来提高效率和编码功能/维护的最佳方法是什么。
非常感谢你的指导/想法,欢呼WL
答案 0 :(得分:1)
每个require模块(defined using define
)都应返回function/object
。显示的分手并不是,而只是分割代码。考虑一些假设的模块桶并将每段代码(或函数)放入模块中。然后将代码分组到require js
模块并返回模块的接口。
让我试着用一个例子进一步解释。
<强> main.js 强>
$(document).ready(function(){
$("#heyINeedMap").click(function(){
require(['map'],function(Map){
Map.render($target);
});
});
});
OR
$(document).ready(function(){
require(['map','geolocation'],function(Map,Geolocation){
window.App.start = true;
window.App.map = Map; //won't suggest, but you can do.
window.App.geolocation = Geolocation;
//do something.
$("#lastCoords").click(function(){
var coords = App.geolocation.getLastSavedCoords();
if(!!coords){
coords = App.geolocation.fetchCurrentCoords();
}
alert(coords);
});
});
});
<强> map.js 强>
define(['jquery'],function($){
var privateVariableAvailableToAllMapInstances = 'something';
var mapType = 'scatter';
return function(){
render: function(el){
//rendering logic goes here
},
doSomethingElse: function(){
privateVariable = 'some new value';
//other logic goes here
},
changeMapType: function(newType){
mapType = newType;
//...
}
}
});
<强> geolocation.js 强>
//Just assuming that it needs jquery & another module called navigation to work.
define(['jquery','navigation'], function($,Gnav){
return {
var coordinates = Gnav.lastSavedCoords;
fetchCurrentCoords: function(){
//coordinates = [79.12213, 172.12342]; //fetch from API/something
return coordinates;
},
getLastSavedCoords: function(){
return coordinates;
}
}
});
希望这能说明如何继续。