草庐IT

通过openlayers加载dwg格式的CAD图并与互联网地图叠加

vjmap 2023-03-28 原文

Openlayers介绍

​ Openlayers是一个基于Javacript开发,免费、开源的前端地图开发库,使用它,可以很容易的开发出WebGIS系统。目前Openlayers支持地图瓦片、矢量数据等众多地图数据格式,支持比较完整的地图交互操作。目前OpenLayers已经成为一个拥有众多开发者和帮助社区的成熟、流行的框架,在国内外的GIS相关行业中得到了广泛的应用。

openlayers 官网地址 https://openlayers.org/

openlayers 源码地址 https://github.com/openlayers/openlayers

Openlayers中加载CAD栅格瓦片

// 地图服务对象,调用唯杰地图服务打开地图,获取地图的元数据
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
// 打开地图
let mapId = "sys_zp";
let res = await svc.openMap({
    mapid: mapId, // 地图ID
    mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开
    style: vjmap.openMapDarkStyle() // div为深色背景颜色时,这里也传深色背景样式
})
if (res.error) {
    // 如果打开出错
    message.error(res.error)
}
// 获取地图范围
let mapBounds = vjmap.GeoBounds.fromString(res.bounds);

//自定义投影参数
let cadProjection = new ol.proj.Projection({
    // extent用于确定缩放级别
    extent: mapBounds.toArray(),
    units: 'm'
});
// 设置每级的分辨率
let resolutions= [];
for(let i = 0; i < 25; i++) {
    resolutions.push(mapBounds.width() / (512 * Math.pow(2, i - 1)))
}
// 增加自定义的cad的坐标系
ol.proj.addProjection(cadProjection);

// 创建openlayer的地图对象
let map = new ol.Map({
    target: 'map', // div的id
    view: new ol.View({
        center: mapBounds.center().toArray(),  // 地图中心点
        projection: cadProjection, // 刚自定义的cad的坐标系
        resolutions:resolutions, // 分辨率
        zoom: 2// 初始缩放级别
    })
});

// 增加一个瓦片图层
let layer = new ol.layer.Tile({
    // 增加一个瓦片数据源
    source: new ol.source.TileImage({
        url: svc.rasterTileUrl() // 唯杰地图服务提供的cad的栅格瓦片服务地址
    })
});
// 在地图中增加上面的瓦片图层
map.addLayer(layer);

Openlayers中加载CAD矢量瓦片


// 增加一个矢量瓦片图层
let layer = new ol.layer.VectorTile({
    // 增加一个瓦片数据源
    source: new ol.source.VectorTile({
        projection: cadProjection,
        format: new ol.format.MVT(),
        url: svc.vectorTileUrl() // 唯杰地图服务提供的cad的矢量瓦片服务地址
    }),
    style: createVjMapVectorStyle(ol.style.Style, ol.style.Fill, ol.style.Stroke, ol.style.Circle)
});
// 在地图中增加上面的瓦片图层
map.addLayer(layer);

Openlayers中选择高亮CAD实体


const highlight_ent = async co => {
    vectorSource.clear();
    let res = await svc.pointQueryFeature({
        x: co[0],
        y: co[1],
        zoom: map.getView().getZoom(),
        fields: ""
    }, pt => {
        // 查询到的每个点进行坐标处理回调
        return mapPrj.fromMercator(pt);// 转成cad的坐标
    })
    if (res && res.result && res.result.length > 0) {
        let features = [];
        for (let ent of res.result) {
            if (ent.geom && ent.geom.geometries) {
                let clr = vjmap.entColorToHtmlColor(ent.color);
                for (let g = 0; g < ent.geom.geometries.length; g++) {
                    features.push({
                        type: "Feature",
                        properties: {
                            objectid: ent.objectid + "_" + g,
                            color: clr,
                            alpha: ent.alpha / 255,
                            lineWidth: 1,
                            name: ent.name,
                            isline: ent.isline,
                            layerindex: ent.layerindex
                        },
                        geometry: ent.geom.geometries[g]
                    })
                }
                // 选择提示
                let content = `feature: ${ent.objectid}; layer: ${cadLayers[ent.layerindex].name}; type: ${ent.name}`
                message.info({ content, key: "info", duration: 3});
            }
        }
        geojsonObject.features = features;
        if (geojsonObject.features.length > 0) {
            vectorSource.addFeatures( new ol.format.GeoJSON().readFeatures(geojsonObject, {dataProjection: cadProjection}))
        }
    }
};

Openlayers中上传打开CAD的DWG图形


// 地图服务对象,调用唯杰地图服务打开地图,获取地图的元数据
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)

// 上传dwg文件
const uploadDwgFile = async file => {
    message.info("正在上传图形,请稍候", 2);
    let res = await svc.uploadMap(file); // 上传地图
    // 输入图id
    let mapid = prompt("请输入图名称ID", res.mapid);
    res.mapid = mapid;
    res.mapopenway = vjmap.MapOpenWay.GeomRender; // 几何渲染,内存渲染用vjmap.MapOpenWay.Memory
    res.isVector = false; // 使用栅格瓦片
    res.style = vjmap.openMapDarkStyle(); // 深色样式,浅色用openMapDarkStyle
    message.info("正在打开图形,请稍候,第一次打开时根据图的大小可能需要几十秒至几分钟不等", 5);
    let data = await svc.openMap(res); // 打开地图
    if (data.error) {
        message.error(data.error)
        return;
    }
    openMap(data);
}

Openlayers中切换CAD图层

// 切换图层
const switchLayer = async layers => {
    let res = await svc.cmdSwitchLayers(layers); // 调用唯杰服务切换图层,返回图层id {layerid: "xxxx"}
    let source = layer.getSource();
    // 重新设置新的唯杰地图服务提供的cad的栅格瓦片服务地址
    source.setUrl(svc.rasterTileUrl());
    // 刷新
    source.refresh();
}

Openlayers中切换CAD图形


const switchToMapId = async (mapId)=> {
    let res = await svc.openMap({
        mapid: mapId, // 地图ID
        mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开
        style: vjmap.openMapDarkStyle() // div为深色背景颜色时,这里也传深色背景样式
    })
    if (res.error) {
        // 如果打开出错
        message.error(res.error)
        return;
    }
// 获取地图范围
    let mapBounds = vjmap.GeoBounds.fromString(res.bounds);

//自定义投影参数
    let cadProjection = new ol.proj.Projection({
        // extent用于确定缩放级别
        extent: mapBounds.toArray(),
        units: 'm'
    });
// 设置每级的分辨率
    let resolutions= [];
    for(let i = 0; i < 25; i++) {
        resolutions.push(mapBounds.width() / (512 * Math.pow(2, i - 1)))
    }
// 增加自定义的cad的坐标系
    ol.proj.addProjection(cadProjection);

// 重新创建openlayer的地图对象
    map = new ol.Map({
        target: createNewMapDivId(), // div的id
        view: new ol.View({
            center: mapBounds.center().toArray(),  // 地图中心点
            projection: cadProjection, // 刚自定义的cad的坐标系
            resolutions:resolutions, // 分辨率
            zoom: 2 // 初始缩放级别
        })
    });

// 增加一个瓦片图层
    let layer = new ol.layer.Tile({
        // 增加一个瓦片数据源
        source: new ol.source.TileImage({
            url: svc.rasterTileUrl() // 唯杰地图服务提供的cad的栅格瓦片服务地址
        })
    });
// 在地图中增加上面的瓦片图层
    map.addLayer(layer);

    map.on('click', (e) => message.info({content: `您点击的坐标为: ${JSON.stringify(e.coordinate)}`, key: "info", duration: 3}));
}

Openlayers中深色浅色切换主题

let curIsDarkTheme = true;
const switchToDarkTheme = async () => {
    if (curIsDarkTheme) return;
    curIsDarkTheme = true;
    document.body.style.background = "#022B4F"; // 背景色改为深色
    await updateStyle(curIsDarkTheme)
}

const switchToLightTheme = async () => {
    if (!curIsDarkTheme) return;
    curIsDarkTheme = false;
    document.body.style.backgroundImage = "linear-gradient(rgba(255, 255, 255, 1), rgba(233,255,255, 1), rgba(233,255,255, 1))"
    await updateStyle(curIsDarkTheme)
}

const updateStyle = async (isDarkTheme) => {
    style.backcolor = isDarkTheme ? 0 : 0xFFFFFF;//深色为黑色,浅色为白色
    let res = await svc.cmdUpdateStyle(style);
    let source = layer.getSource();
    // 重新设置新的唯杰地图服务提供的cad的栅格瓦片服务地址
    source.setUrl(svc.rasterTileUrl());
    // 刷新
    source.refresh();
}

Openlayers中自定义CAD地图样式

通过修改CAD地图后台样式数据自定义地图


// 更改样式
const expressionList = [] ;// 表达式数组
const updateStyle = async (style) => {
    let res = await svc.cmdUpdateStyle({
        name: "customStyle2",
        backcolor: 0,
        expression: expressionList.join("\n"),
        ...style
    });
    let source = layer.getSource();
    // 重新设置新的唯杰地图服务提供的cad的栅格瓦片服务地址
    source.setUrl(svc.rasterTileUrl());
    // 刷新
    source.refresh();
}

// 表达式语法和变量请参考
// 服务端条件查询和表达式查询 https://vjmap.com/guide/svrStyleVar.html
// 服务端渲染表达式语法 https://vjmap.com/guide/expr.html

// 修改颜色  红color.r, 绿color.g, 蓝color.b, 透明度color.a,如果输入了级别的话,表示此级别及以上的设置
const modifyColor = (color, zoom) => {
    let result = "";
    let z = Number.isInteger(zoom) ? `[${zoom + 1}]` : '';
    if ("r" in color) result += `gOutColorRed${z}:=${color.r};`;
    if ("g" in color) result += `gOutColorGreen${z}:=${color.g};`;
    if ("b" in color) result += `gOutColorBlue${z}:=${color.b};`;
    if ("a" in color) result += `gOutColorAlpha${z}:=${color.a};`;
    return result;
}

Openlayers中对CAD图处理组合

对多个cad图进行图层开关裁剪旋转缩放处理后合并成一个新的cad图


// 组合成新的图,将sys_world图进行一定的处理后,再与sys_hello进行合成,生成新的地图文件名
let rsp = await svc.composeNewMap([
    {
        mapid: "sys_world", // 地图id
        // 下面的参数可以根据实际需要来设置,可以对图层,范围,坐标转换来进行处理
        layers: ["经纬度标注","COUNTRY"], // 要显示的图层名称列表
        //clipbounds: [10201.981489534268, 9040.030491346213, 26501.267379,  4445.465999], // 要显示的范围
        //fourParameter: [0,0,1,0] // 对地图进行四参数转换计算
    },
    {
        mapid: "sys_hello"
    }
])
if (!rsp.status) {
    message.error(rsp.error)
}
// 返回结果为
/*
{
    "fileid": "pec9c5f73f1d",
    "mapdependencies": "sys_world||sys_hello",
    "mapfrom": "sys_world&&v1&&&&0&&&&&&&&&&00A0&&10||sys_hello&&v1&&&&0&&&&&&&&&&&&2",
    "status": true
}
 */

Openlayers中查询图中所有文字并绘制边框


// 实体类型ID和名称映射
const { entTypeIdMap } = await svc.getConstData();
const getTypeNameById = name => {
    for(let id in entTypeIdMap) {
        if (entTypeIdMap[id] == name) {
            return id
        }
    }
}
const queryTextAndDrawBounds = async () => {
    let queryTextEntTypeId = getTypeNameById("AcDbText"); // 单行文字
    let queryMTextEntTypeId = getTypeNameById("AcDbMText"); // 多行文字
    let queryAttDefEntTypeId = getTypeNameById("AcDbAttributeDefinition"); // 属性定义文字
    let queryAttEntTypeId = getTypeNameById("AcDbAttribute"); // 属性文字
    let query = await svc.conditionQueryFeature({
        condition: `name='${queryTextEntTypeId}' or name='${queryMTextEntTypeId}' or name='${queryAttDefEntTypeId}' or name='${queryAttEntTypeId}'`, // 只需要写sql语句where后面的条件内容,字段内容请参考文档"服务端条件查询和表达式查询"
        fields: "",
        limit: 100000 //设置很大,相当于把所有的圆都查出来。不传的话,默认只能取100条
    }, pt => {
        // 查询到的每个点进行坐标处理回调
        return mapPrj.fromMercator(pt);// 转成cad的坐标
    })
    if (query.error) {
        message.error(query.error)
    } else {
        message.info(`查询到符合的记数条数:${query.recordCount}`)

        if (query.recordCount > 0) {
            let features = [];
            for(var i = 0; i < query.recordCount; i++) {
                let bounds = vjmap.getEnvelopBounds(query.result[i].envelop, mapPrj);
                let clr = vjmap.entColorToHtmlColor(query.result[i].color); // 实体颜色转html颜色(

                features.push({
                    type: "Feature",
                    properties: {
                        name: "objectid:" + query.result[i].objectid,
                        color: clr
                    },
                    geometry: {
                        'type': 'Polygon',
                        'coordinates': [
                            bounds.toPointArray(),
                        ],
                    }
                })
            }

            if (!vectorSource) {
                // 如果之前没有高亮矢量图层
                addHighLightLayer();
            }
            vectorSource.clear();
            let geojsonObject = {
                'type': 'FeatureCollection',
                'features': features
            }
            // 修改矢量数据源数据
            vectorSource.addFeatures( new ol.format.GeoJSON().readFeatures(geojsonObject, {dataProjection: cadProjection}))
        }
    }
}

Openlayers中图形绘制


const source = new ol.source.Vector({wrapX: false});

const vector = new ol.layer.Vector({
    source: source,
});

map.addLayer(vector);

let draw; // global so we can remove it later
function addInteraction(value) {
    map.removeInteraction(draw);
    if (value !== 'None') {
        draw = new ol.interaction.Draw({
            source: source,
            type: value,
        });
        map.addInteraction(draw);
    }
}

addInteraction('Point');

Openlayers中CAD图叠加互联网地图[CAD为底图]


// 增加高德地图底图
let gdlayer;
const addGaodeMap = async (isRoadway) => {
    const tileUrl = svc.webMapUrl({
        tileCrs: "gcj02",
        tileUrl:  isRoadway ? [
                "https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"
            ] :
            /* 如果用影像 */
            [
                "https://webst0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=6&x={x}&y={y}&z={z}",
                "https://webst0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"
            ],
        tileSize: 256,
        tileRetina: 1,
        tileMaxZoom: 18,
        tileShards: "1,2,3,4",
        tileToken: "",
        tileFlipY: false,
        mapbounds: res.bounds,
        srs: "EPSG:4527",// 可通过前两位获取 vjmap.transform.getEpsgParam(vjmap.transform.EpsgCrsTypes.CGCS2000, 39).epsg
        // 因为sys_cad2000这个图只有6位,没有带系。需要在坐标转换前平移下带系  https://blog.csdn.net/thinkpang/article/details/124172626
        fourParameterBefore: "39000000,0,1,0"
    })


    // 增加一个瓦片图层
    gdlayer = new ol.layer.Tile({
        // 增加一个瓦片数据源
        source: new ol.source.TileImage({
            url: tileUrl
        })
    });
    gdlayer.setZIndex(-1);
// 在地图中增加上面的瓦片图层
    map.addLayer(gdlayer);


    // cad坐标与高德坐标相互转换示例
    let webCo = await cad2webCoordinate(center, false); // cad转高德
    let cadCo = await web2cadCoordinate(webCo, false); // 高德转cad
    console.log(center, webCo, cadCo)
}

Openlayers中互联网地图自动叠加CAD图[互联网图为底图]


let cadEpsg = "EPSG:4544";// cad图的espg代号
// 增加cad的wms图层
let wmsUrl = svc.wmsTileUrl({
    mapid: mapId, // 地图id
    layers: layer, // 图层名称
    bbox: '', // bbox这里不需要
    srs: "EPSG:3857", //
    crs: cadEpsg
})
function getQueryStringArgs(url) {
    let theRequest = {};
    let idx = url.indexOf("?");
    if (idx != -1) {
        let str = url.substr(idx + 1);
        let strs = str.split("&");
        for (let i = 0; i < strs.length; i++) {
            let items = strs[i].split("=");
            theRequest[items[0]] = items[1];
        }
    }
    return theRequest;
}

let mapBounds = vjmap.GeoBounds.fromString(res.bounds);
// cad图坐标转web wgs84坐标
const cadToWebCoordinate = async point => {
    let co = await svc.cmdTransform(cadEpsg, "EPSG:4326", point);
    return co[0]
}
// cad转wgs84经纬度
let boundsMin = await cadToWebCoordinate(mapBounds.min);
let boundsMax = await cadToWebCoordinate(mapBounds.max);
// wgs84经纬度转墨卡托
boundsMin = vjmap.Projection.lngLat2Mercator(boundsMin);
boundsMax = vjmap.Projection.lngLat2Mercator(boundsMax);

// 在openlayer中增加wms图层
map.addLayer(new ol.layer.Tile({
    // 范围
    extent: [boundsMin[0], boundsMin[1], boundsMax[0], boundsMax[1]],
    source: new ol.source.TileWMS({
        url: wmsUrl.substr(0, wmsUrl.indexOf("?")),
        params: {...getQueryStringArgs(wmsUrl),'TILED': true}
    }),
}))

Openlayers中互联网地图公共点叠加CAD图[互联网图为底图]


// cad上面的点坐标
let cadPoints = [
    vjmap.geoPoint([587464448.8435847, 3104003685.208651,]),
    vjmap.geoPoint([587761927.7224838, 3104005967.655292]),
    vjmap.geoPoint([587463688.0280377, 3103796743.3798513]),
    vjmap.geoPoint([587760406.0913897, 3103793700.1176634])
];

// 在互联网图上面拾取的与上面的点一一对应的坐标(wgs84坐标)
let webPoints = [
    vjmap.geoPoint([116.48476281710168, 39.96200739703454]),
    vjmap.geoPoint([116.48746772021137, 39.96022062215167]),
    vjmap.geoPoint([116.48585059441585, 39.9588451134361]),
    vjmap.geoPoint([116.48317418949145, 39.960515760972356])
]
// 通过坐标参数求出四参数
let epsg3857Points = webPoints.map(w => vjmap.geoPoint(vjmap.Projection.lngLat2Mercator(w)));
let param = vjmap.coordTransfromGetFourParamter(epsg3857Points, cadPoints , false); // 这里考虑旋转
let fourparam = [param.dx, param.dy, param.scale, param.rotate]

// wms图层地址
const getCadWmsUrl = (transparent) => {
    let wmsUrl = svc.wmsTileUrl({
        mapid: mapId, // 地图id
        layers: layer, // 图层名称
        bbox: '', // bbox这里不需要
        fourParameter: fourparam,
        transparent: transparent,
        backgroundColor: 'rgba(240, 255, 255)' // 不透明时有效
    })
    return wmsUrl
}

let mapBounds = vjmap.GeoBounds.fromString(res.bounds);
let cadPrj = new vjmap.GeoProjection(mapBounds);


// cad图坐标转3857坐标
const cadToWebCoordinate = point => {
    // 再调用四参数反算求出web的坐标
    return vjmap.coordTransfromByInvFourParamter(vjmap.geoPoint(point), param)
}
// 3857转cad图坐标
const webToCadCoordinate = point => {
    return vjmap.coordTransfromByFourParamter(vjmap.geoPoint(point), param)
}

let wmsLayer;
const addWmsLayer = async (transparent)=> {
    removeWmsLayer();
    let wmsUrl = getCadWmsUrl(transparent);
    wmsLayer = new ol.layer.Tile({
        // 范围
        extent: bounds.toArray(),
        source: new ol.source.TileWMS({
            url: wmsUrl.substr(0, wmsUrl.indexOf("?")),
            params: {...getQueryStringArgs(wmsUrl),'TILED': true}
        }),
    });
    // 在openlayer中增加wms图层
    map.addLayer(wmsLayer);
}

最后

可点击 https://vjmap.com/demo/#/demo/map/openlayers/01olraster 在线体验上面功能

如果需要用openlayers来加载CAD图进行开发,请参考示例 https://vjmap.com/demo/#/demo/map/openlayers/01olraster

如果需要用leaflet来加载CAD图进行开发,请参考示例 https://vjmap.com/demo/#/demo/map/leaflet/01leafletraster

如果需要用maptalks来加载CAD图进行开发,请参考示例 https://vjmap.com/demo/#/demo/map/maptalks/01maptalksraster

如何基于vue3来开发openlayers应用,可查看此开源代码 https://github.com/MelihAltintas/vue3-openlayers

如何基于vue2来开发openlayers应用,可查看此开源代码 https://github.com/ghettovoice/vuelayers

有关通过openlayers加载dwg格式的CAD图并与互联网地图叠加的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  3. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  4. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  5. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  6. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  7. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  8. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  9. ruby-on-rails - 将 Ruby 中的日期/时间格式化为 YYYY-MM-DD HH :MM:SS - 2

    这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build

  10. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

随机推荐