把原来的数组20条,按照每两条一组,从新组成一个数据

本文介绍了一种使用PHP对数据库查询结果进行分组的方法。通过两种不同的方案对比,展示了如何从数据库中获取特定类型的数据,并对其进行有效分组,以便更好地进行后续处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方案1:

 1 $list=$list = DB::table('demo')->where('type', '>', 1000)->orderBy('created', 'desc')
 2             ->limit(20)->get()->toArray();
 3 $data = [];
 4 $count = count($list);
 5 for ($i=0; $i <10 ; $i++) { 
 6     $d = [];
 7     $d[0] = $list[$i*2];
 8     $d[1] = $list[$i*2+1];
 9     array_push($data, $d);
10 }

方案2:

1 for ($i = 0; $i < floor(($count / 2)); $i++) {
2     for ($j = 0; $j < 2; $j++) {
3         $data[$i][$j] = $list[$i * 2 + $j];
4     }
5 }

 

转载于:https://www.cnblogs.com/acoll/articles/7050365.html

<think>我们将在Leaflet中实现一个可拖动的直角虚线,该虚线由两个线段组成:一段水平线和一段垂直线,形成一个直角。需求:1.虚线样式(直角)2.两个端点可以拖动(起点和终点),拖动时动态调整横向或纵向的线段长度3.当拖动起点或终点时,另一段线段会相应地调整方向(横向变纵向,纵向变横向)以保持直角。思路:我们将创建两个折线(Polyline)对象:一水平线和一垂直线,它们连接起来形成直角。然后,我们在两个端点(起点和终点)处放置可拖动的标记(Marker,并设置draggable=true)。当拖动起点时,我们更新水平线的起点和垂直线的起点(同时保持直角结构);当拖动终点时,更新垂直线的终点和水平线的终点(同样保持直角结构)。注意:直角虚线的两个线段方向可以是先水平再垂直,或者先垂直再水平。这里我们假设先水平再垂直(即起点水平移动,然后垂直移动到达终点)。但是,为了在拖动时能够灵活调整,我们可能需要根据拖动点的位置来决定方向,不过题目要求是直角,所以每次拖动时,我们固定一个方向(例如,起点到转折点水平,转折点到终点垂直)。然而,为了满足“动态调整横向或纵向的线段长度”,并保持直角,我们这样设计:起点(A点)和终点(C点)以及一个转折点(B点)。其中,A到B是水平线,B到C是垂直线。或者也可以A到B是垂直线,B到C是水平线。这个取决于起点和终点的相对位置。但我们的需求是“直角虚线”,所以我们固定这样的结构:从起点出发,先画水平线到中间点,再画垂直线到终点。但是当起点和终点移动时,可能水平线和垂直线的方向会改变(比如原来起点在终点左边,那么起点向右画水平线;如果起点在终点右边,那么应该向左画水平线)。所以我们需要根据起点和终点的位置动态判断中间点。但是,为了简化,我们可以在拖动时保持方向不变吗?题目要求动态调整横向或纵向,我们可以这样:当我们拖动起点或终点时,我们保持线段的方向(即水平线段始终是水平的,垂直线段始终是垂直的),但允许长度变化,并调整中间点的位置。具体步骤:1.初始化地图。2.创建两个点(起点和终点),以及一个中间点(转折点)。中间点的初始位置为:起点和终点的水平方向和垂直方向的交点。注意:起点和终点的水平线和垂直线交点即为转折点,所以转折点坐标是(起点的纬度,终点的经度)或(终点的纬度,起点的经度)?实际上,我们要求的是直角,所以转折点应该是起点和终点构成的矩形的另外两个角点之一?不对。正确的中间点应该是:起点为A(lat1,lng1),终点为C(lat2,lng2)。然后我们画直角有两种情况:情况1:A点水平移动至B(lat1,lng2),再垂直移动至C(lat2,lng2)。(先水平后垂直)情况2:A点垂直移动至B(lat2,lng1),再水平移动至C(lat2,lng2)。(先垂直后水平)我们选择哪一种?这里可以选择最短路径,或者固定一种模式。题目没有要求,我们就固定为情况1:先水平再垂直。因此,转折点B的坐标为(lat1,lng2)[注意:起点A的纬度,终点C的经度]。3.创建两条线:line1:起点A->转折点B(水平线)line2:转折点B->终点C(垂直线)4.创建两个可拖动的标记:一个在起点A,一个在终点C。5.当拖动起点标记时:起点A的位置更新,然后转折点B的位置更新为(A.lat,C.lng)[因为要保持水平线从A出发,水平移动(纬度不变,经度变化到C的经度)到转折点B]然后更新两条折线:line1更新为[A,B],line2更新为[B,C](注意B点位置变了,但终点C未变)6.当拖动终点标记时:终点C的位置更新,然后转折点B的位置更新为(A.lat,C.lng)[起点A的纬度,终点C的经度]然后更新两条折线:line1还是A到B(A不变,B的位置变为(A.lat,C.lng)),line2更新为B到C。注意:这里转折点B是动态计算出来的,而不是一个实际的标记点(所以它不可拖动)。7.虚线样式:在创建折线时设置dash选项。但是,我们也可以使用一个折线对象来包含两个线段?但折线对象是连续的,而直角虚线在转折处是断开的(虚线),所以用两个折线对象更合适。8.转折点B实际上不需要标记,因为它不是可拖动的,我们只拖动起点和终点。代码实现:步骤:1.初始化地图和图层。2.定义初始点(起点和终点)。3.计算转折点(B点)。4.创建两条折线(虚线),添加到地图。5.创建两个可拖动的标记(起点和终点),并添加到地图。6.为标记添加拖动事件监听器。在事件监听器中更新折线坐标:起点标记拖动事件:当拖动时,更新A点坐标,然后计算新的B点(A点的纬度,C点的经度),然后更新两条线:line1:[A,B]line2:[B,C]终点标记拖动事件:当拖动时,更新C点坐标,然后计算新的B点(A点的纬度,C点的经度),然后更新两条线:line1:[A,B](注意:A点没变,所以line1的起点是A,终点是B)line2:[B,C]注意:这样在拖动时,转折点B的纬度始终等于起点A的纬度,经度始终等于终点C的经度。因此,在拖动起点时,水平线变化(起点移动,水平线长度变化)同时垂直线也会变化(因为转折点B的经度不变,但纬度还是起点A的纬度,所以垂直线从B到C是垂直的,但是B点的位置变了,所以垂直线的长度也会变)?实际上,当我们拖动起点时,A点位置变化,B点位置变化(纬度变成了新A点的纬度),那么垂直线就变成了从新的B(新A点的纬度,原C点经度)到C点(位置未变),所以垂直线长度会变。同时,在拖动终点时,C点位置变化,B点位置变化(经度变成新C点的经度),那么水平线就变成从A(不变)到B(新B点:A点纬度,新C点经度)的长度变了;垂直线也变成了新B点到新C点的长度。9.注意:在Leaflet中,设置折线的坐标使用setLatLngs方法(传入坐标数组,每折线两个点)。示例代码:注意:这里使用ES6语法。我们将创建两个折线对象和一个转折点(不用显示标记)。同时创建两个标记(起点和终点),并绑定drag事件。代码结构:letmap=L.map(...);...//初始化地图//初始点letstartPoint=L.latLng(39.907,116.397);//起点AletendPoint=L.latLng(39.907,116.497);//终点C//计算转折点B(起点纬度,终点经度)letbreakPoint=L.latLng(startPoint.lat,endPoint.lng);//创建水平虚线(起点A到转折点B)letline1=L.polyline([startPoint,breakPoint],{dashArray:'5,5',//虚线样式color:'blue'}).addTo(map);//创建垂直虚线(转折点B到终点C)letline2=L.polyline([breakPoint,endPoint],{dashArray:'5,5',color:'blue'}).addTo(map);//创建可拖动的起点标记letstartMarker=L.marker(startPoint,{draggable:true}).addTo(map);//创建可拖动的终点标记letendMarker=L.marker(endPoint,{draggable:true}).addTo(map);//绑定起点标记的拖动事件startMarker.on('drag',function(e){//获取新的起点位置startPoint=e.target.getLatLng();//重新计算转折点B(新起点的纬度,原终点的经度)breakPoint=L.latLng(startPoint.lat,endPoint.lng);//更新折线line1.setLatLngs([startPoint,breakPoint]);line2.setLatLngs([breakPoint,endPoint]);//终点没变,但是转折点变了,所以垂直线会变});//绑定终点标记的拖动事件endMarker.on('drag',function(e){endPoint=e.target.getLatLng();//重新计算转折点B(原起点的纬度,新终点的经度)breakPoint=L.latLng(startPoint.lat,endPoint.lng);//更新折线line1.setLatLngs([startPoint,breakPoint]);//起点没变,但是转折点变了,所以水平线会变(长度)line2.setLatLngs([breakPoint,endPoint]);});10.注意:这样实现,在拖动起点时,转折点B的纬度会随起点变化,经度使用终点的经度;拖动终点时,转折点B的经度会随终点变化,纬度使用起点的纬度。11.但是,这样实现的直角虚线只能保持先水平后垂直。如果我们想要在拖动时改变方向(比如当终点在起点左边时,水平线向左延伸)?实际上,因为转折点B是起点纬度和终点经度的组合,这样在起点纬度不变的情况下,拖动终点改变经度,水平线段会随着终点经度的变化而延长或缩短方向(即如果终点在起点左边,那么水平线就会向左延伸,因为转折点B的经度是终点的经度,而起点纬度不变,所以水平线连接起点和转折点,起点位置不动,转折点在左边,所以水平线向左延伸)。因此,这个转折点B的位置是合理的。12.还有一个问题:如果起点和终点的纬度相同,那么垂直线段长度为0?没关系,这样只会显示一水平线。同理,如果起点和终点的经度相同,那么水平线段长度为0,只显示一垂直线。13.优化:可以添加一个转折点标记并使其可拖动?但题目要求是端点(起点和终点)拖动,所以不需要转折点拖动。14.注意事项:在Leaflet中,折线坐标点数组是[点1,点2,...,点n]。我们每折线只有两个点。15.完整代码示例:注意:这里只是核心代码,需要放入到完整的Leaflet项目中。改进:我们也可以用一个折线对象来表示整个直角线(这样在转折处不连续,因为虚线是断开的,所以用两个折线对象更简单),但是这样就不连续了。所以两个折线对象是合理的。16.可能的改进:在拖动起点或终点时,可能希望重新计算哪一个是水平线哪一个是垂直线?即动态决定方向(先水平还是先垂直)。但题目要求直角,并且要求拖动端点时调整横向纵向线段长度,所以固定先水平后垂直也是可以的。但是,如果用户将起点从左边拖到终点的右边,那么水平线就变成从起点向右延伸到终点经度?还是向左延伸到终点经度?实际上,我们是动态计算转折点B,在起点标记拖动事件中,转折点B的经度始终是终点的经度(不管在左边还是右边),所以如果起点被拖动到终点的右边(此时终点的经度小于起点的经度),那么水平线就会从起点(在右侧)向左延伸到终点的经度位置(转折点B)。这样是合理的。17.测试:请确保在完整的Leaflet环境中运行。18.特殊情况:当起点和终点经度相同,那么水平线长度为零;纬度相同,则垂直线长度为零。19.代码封装:如果需要在多处使用,可以封装成一个类。下面给出一个可运行的示例代码框架(HTML):</think> ### 在 Leaflet 中实现可拖动的直角虚线 我将分步骤解释如何实现带端点拖动功能的直角虚线,并在拖动时动态调整横向或纵向线段长度。核心是使用 Leaflet 的 `Polyline`、`Marker` 和事件监听机制实现动态路径更新。 #### 解决方案代码 ```javascript // 初始化地图 const map = L.map('map').setView([51.505, -0.09], 13); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); // 直角路径的起点、转折点和终点 let pointA = L.latLng(51.5, -0.1); // 起点 let pointB = L.latLng(51.5, -0.05); // 转折点 (水平线终点/垂直线起点) let pointC = L.latLng(51.52, -0.05); // 终点 // 创建直角虚线路径 const createRightAngleLine = () => { const horizontalLine = L.polyline( [pointA, pointB], { dashArray: '10, 10', color: 'blue' } ); const verticalLine = L.polyline( [pointB, pointC], { dashArray: '10, 10', color: 'blue' } ); return { horizontalLine, verticalLine }; }; // 添加路径到地图 let { horizontalLine, verticalLine } = createRightAngleLine(); horizontalLine.addTo(map); verticalLine.addTo(map); // 创建可拖动端点标记 const startMarker = L.marker(pointA, { draggable: true }).addTo(map); const endMarker = L.marker(pointC, { draggable: true }).addTo(map); // 拖动起点时更新路径 startMarker.on('drag', (e) => { pointA = e.target.getLatLng(); // 只更新水平线段终点(B点)的纬度(保持纵向位置不变) pointB = L.latLng(pointA.lat, pointB.lng); // 更新水平线段 horizontalLine.setLatLngs([pointA, pointB]); // 更新垂直线段起点(保持垂直关系) verticalLine.setLatLngs([pointB, pointC]); }); // 拖动终点时更新路径 endMarker.on('drag', (e) => { pointC = e.target.getLatLng(); // 只更新垂直线段起点(B点)的经度(保持横向位置不变) pointB = L.latLng(pointB.lat, pointC.lng); // 更新垂直线段 verticalLine.setLatLngs([pointB, pointC]); // 更新水平线段终点(保持垂直关系) horizontalLine.setLatLngs([pointA, pointB]); }); ``` #### 关键实现原理 1. **虚线效果**: 使用 `dashArray: '10, 10'` 参数创建虚线样式,其中数字表示实线和空白的长度比 2. **直角路径结构**: - 水平线段:连接起点 `pointA` 和转折点 `pointB` - 垂直线段:连接转折点 `pointB` 和终点 `pointC` 3. **端点拖动逻辑**: ```mermaid graph LR A[拖动起点] --> B[更新水平线长度] B --> C[固定垂直线起点经度] D[拖动终点] --> E[更新垂直线长度] E --> F[固定水平线终点纬度] ``` 4. **动态长度调整**: - 拖动起点:仅修改 `pointB` 的**纬度**(垂直坐标),保持水平线水平 - 拖动终点:仅修改 `pointB` 的**经度**(水平坐标),保持垂直线垂直 #### 功能扩展建议 1. **显示线段长度**: 添加 `L.tooltip` 实时显示当前线段长度: ```javascript horizontalLine.bindTooltip('水平距离:' + pointA.distanceTo(pointB).toFixed(0) + '米'); verticalLine.bindTooltip('垂直距离:' + pointB.distanceTo(pointC).toFixed(0) + '米'); ``` 2. **直角方向切换**: 增加切换按钮改变直角方向(先垂直后水平): ```javascript let isHorizontalFirst = true; // 默认先水平后垂直 function updateLineDirection() { // 根据 isHorizontalFirst 重新计算 pointB 位置 // 更新线段连接顺序 } ``` 3. **自定义样式**: ```javascript const lineStyle = { dashArray: '15, 10, 5, 10', // 更复杂的虚线模式 color: '#ff7800', opacity: 0.7, weight: 6 }; ``` #### 常见问题解决 - **直角变形问题**:在拖动回调中固定未拖动坐标轴的值(如拖动起点时固定经度) - **性能优化**:使用 `L.LayerGroup` 管理路径和标记,减少 DOM 操作: ```javascript const lineGroup = L.layerGroup([horizontalLine, verticalLine]).addTo(map); ``` - **移动端适配**:添加 `tap: false` 参数防止与地图点击事件冲突: ```javascript const marker = L.marker(point, { draggable: true, tap: false }); ``` [^1]: Leaflet官方文档 - 矢量图层和标记交互 [^2]: GIS中的直角路径规划算法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值