我是 Javascript 新手,因此 requireJS - 我目前正在使用 Openlayers 3 示例自学,其中我刚刚附加到一个大型 JS 文件。看到这很快变得不守规矩,我阅读了有关 RequireJS 的内容,并认为我应该从一开始就养成正确做事的习惯; “这就是我遇到问题的地方”。
[我认为这并不重要,但我正在使用 Asp.net MVC] 基本上,我希望将文件分成较小的相关模块,例如
- map [由所有模块使用并启动基础层 map ]
- 绘制[处理点/多边形等并添加到 map 中 另一层]
- 地理位置[包含用于绘图的地理定位功能]
- 等等,等等
...可以灵活地立即激活所有层,或者使用易于管理的 JS 代码来选择少数层。
我曾多次尝试将此代码分解为单独的 JS 文件,[ map /绘制/地理定位],但都失败了,因为我觉得我没有掌握 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干杯
最佳答案
每个 require 模块(使用 Define 定义
)都应该返回一个函数/对象
。所显示的分解并没有,而是只是拆分了代码。考虑一些假设的模块桶,并将每段代码(或函数)放入一个模块中。然后将代码分组到 require js
模块中并返回该模块的接口(interface)。
让我尝试用一个例子进一步解释。
main.js
$(document).ready(function(){
$("#heyINeedMap").click(function(){
require(['map'],function(Map){
Map.render($target);
});
});
});
或者
$(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;
}
}
});
希望这能提供有关如何继续的想法。
关于javascript - 如何使用 RequireJS 分解大型 Javascript 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31932996/