Ios 使用图案图像在MKMapView上绘制线
我尝试在带有图案图像的Ios 使用图案图像在MKMapView上绘制线,ios,mkmapview,mkoverlay,Ios,Mkmapview,Mkoverlay,我尝试在带有图案图像的MKMapView上画一条线。 通过添加自定义的mkmappoverlay视图完成绘图 我能画出这条线,但似乎只使用图案图像最左边、最上面的像素,而不是整个图像 以下是我的绘图程序: void drawPatternCellCallback(void *info, CGContextRef cgContext) { UIImage *patternImage = [UIImage imageNamed:@"tmpLine"]; CGContextDrawIm
MKMapView
上画一条线。
通过添加自定义的mkmappoverlay
视图完成绘图
我能画出这条线,但似乎只使用图案图像最左边、最上面的像素,而不是整个图像
以下是我的绘图程序:
void drawPatternCellCallback(void *info, CGContextRef cgContext)
{
UIImage *patternImage = [UIImage imageNamed:@"tmpLine"];
CGContextDrawImage(cgContext, CGRectMake(0, 0, patternImage.size.width, patternImage.size.height), patternImage.CGImage);
}
- (void)drawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
inContext:(CGContextRef)context
{
float alpha = 1;
float tileW = 6.0f;
float tileH = 4.0f;
CGFloat lineWidth = MKRoadWidthAtZoomScale(zoomScale)*2;
CGMutablePathRef path = CGPathCreateMutable();
if (path != nil)
{
//setup styles
CGContextSetRGBStrokeColor(context, 0.0f, 0.0f, 1.0f, 0.5f);
const CGPatternCallbacks kPatternCallbacks = {0, drawPatternCellCallback, NULL};
CGPatternRef strokePattern = CGPatternCreate(
NULL,
CGRectMake(0, 0, tileW, tileH),
CGAffineTransformIdentity,
tileW, // horizontal spacing
tileH,// vertical spacing
kCGPatternTilingConstantSpacing,
true,
&kPatternCallbacks);
//color sapce
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetStrokeColorSpace(context, patternSpace);
//pattern
CGContextSetStrokePattern(context, strokePattern, &alpha);
//joins/ends
CGContextSetLineJoin(context, kCGLineJoinMiter);
CGContextSetLineCap(context, kCGLineCapButt);
CGContextSetLineWidth(context, lineWidth);
//OK, let's draw it
CGPoint firstCGPoint = [self pointForMapPoint:self.point1];
CGPoint lastCGPoint = [self pointForMapPoint:self.point2];
CGPathMoveToPoint(path, NULL, lastCGPoint.x, lastCGPoint.y);
CGPathAddLineToPoint(path, NULL, firstCGPoint.x, firstCGPoint.y);
CGContextAddPath(context, path);
CGContextStrokePath(context);
//house hold
CGPathRelease(path);
CGPatternRelease(strokePattern);
CGColorSpaceRelease(patternSpace);
}
}
知道怎么了吗
塔克斯 我最终采用了完全不同的策略。 我现在依赖于
MKPolyLine
,而不是通过自己的覆盖添加
使用以下代码,我能够在MKMapView
上从点a到点B添加一条伪动画线
代码稍微延迟一下,将几个覆盖添加到MKMapViews,给人一种动画的感觉
不是最漂亮的解决方案但它在实际操作中看起来相当不错:-)
/*启动动画*/
-(无效)plotRouteOnMap
{
[self.mapView removeOverlays:self.mapView.overlays];
//计算两个位置之间的位置数
self.points=[self-getPointsOnRouteFrom:
致:
onMapView:self.mapView];
[self addOverlysFromPointsWithStartFrom:[NSNumber numberWithInt:1]];
}
/*根据地图视图将CGPoint转换为CLLocation*/
-(CLLocation*)点到位置:(MKMapView*)mapView fromPoint:(CGPoint)fromPoint
{
CLLocationCoordinate2D坐标=[mapView convertPoint:fromPoint-toCoordinateFromView:mapView];
返回[[[CLLocation alloc]initWithLatitude:coord.latitude经度:coord.latitude]autorelease];
}
/*获取从到之间的位置对象列表*/
-(NSArray*)getPointsOnRouteFrom:(CLLocation*)from to:(CLLocation*)to onMapView:(MKMapView*)mapView
{
int NUMBER_OF_PIXELS_TO_SKIP=10;//数字越小,动画越流畅,但会产生更多层
NSMutableArray*ret=[NSMutableArray];
CGPoint fromPoint=[mapView convertCoordinate:from.coordinate toPointToView:mapView];
CGPoint toPoint=[mapView convertCoordinate:to.coordinate toPointToView:mapView];
NSArray*allPixels=[self-getAllPointsFromPoint:fromPoint-toPoint:toPoint];
对于(int i=0;i<[所有像素计数];i+=像素数{
NSValue*pointVal=[allPixels objectAtIndex:i];
[ret addObject:[self pointToLocation:mapView fromPoint:[pointVal CGPointValue]];
}
[ret addObject:[self pointToLocation:mapView fromPoint:toPoint]];
返回ret;
}
/*计算从点到顶点的所有像素*/
-(NSArray*)GetAllPoints frompoint:(CGPoint)fPoint toPoint:(CGPoint)tPoint
{
/*Bresenham直线算法的简化实现*/
NSMutableArray*ret=[NSMutableArray];
浮动deltaX=fabsf(tPoint.x-fPoint.x);
浮点deltaY=fabsf(tPoint.y-fPoint.y);
浮点x=fPoint.x;
浮点y=fPoint.y;
浮动误差=deltaX deltaY;
浮动sx=-0.5;
浮动sy=-0.5;
如果(fPoint.xSwift接受答案的版本
使用mkoverlayrender将图像添加为覆盖
func addLayersOfAnimatingOverlay() {
let sourcePoint = // enter as CLLocation
let destinationPoint = // enter as CLLocation
let pointsCoordinatesArray = self.getLocationArrayFrom(startLocation: sourcePoint, endLocation: destinationPoint)
//add overlay on above coordinates
DispatchQueue.main.async{
self.addDirectionOverlayInMap(locationArray: self.pointsCoordinates1, title: "1")
}
获取多段线中的坐标的步骤
func getLocationArrayFrom(startLocation: CLLocation, endLocation: CLLocation) -> [CLLocationCoordinate2D] {
var coordinatesArray: [CLLocationCoordinate2D] = []
if let points = helperClass.getPointsOnRoute(from: startLocation, to: endLocation, on: mapView) {
for point in points {
let coordinate = point.coordinate
coordinatesArray.append(coordinate)
}
}
return coordinatesArray
}
//MARK: get cordinates from line
func getPointsOnRoute(from: CLLocation?, to: CLLocation?, on mapView: MKMapView?) -> [CLLocation]? {
let NUMBER_OF_PIXELS_TO_SKIP: Int = 120
//lower number will give a more smooth animation, but will result in more layers
var ret = [Any]()
var fromPoint: CGPoint? = nil
if let aCoordinate = from?.coordinate {
fromPoint = mapView?.convert(aCoordinate, toPointTo: mapView)
}
var toPoint: CGPoint? = nil
if let aCoordinate = to?.coordinate {
toPoint = mapView?.convert(aCoordinate, toPointTo: mapView)
}
let allPixels = getAllPoints(from: fromPoint!, to: toPoint!)
var i = 0
while i < (allPixels?.count)! {
let pointVal = allPixels![i] as? NSValue
ret.append(point(toLocation: mapView, from: (pointVal?.cgPointValue)!)!)
i += NUMBER_OF_PIXELS_TO_SKIP
}
ret.append(point(toLocation: mapView, from: toPoint!)!)
return ret as? [CLLocation]
}
/**convert a CGPoint to a CLLocation according to a mapView*/
func point(toLocation mapView: MKMapView?, from fromPoint: CGPoint) -> CLLocation? {
let coord: CLLocationCoordinate2D? = mapView?.convert(fromPoint, toCoordinateFrom: mapView)
return CLLocation(latitude: coord?.latitude ?? 0, longitude: coord?.longitude ?? 0)
}
func getAllPoints(from fPoint: CGPoint, to tPoint: CGPoint) -> [Any]? {
/*Simplyfied implementation of Bresenham's line algoritme */
var ret = [AnyHashable]()
let deltaX: Float = fabsf(Float(tPoint.x - fPoint.x))
let deltaY: Float = fabsf(Float(tPoint.y - fPoint.y))
var x: Float = Float(fPoint.x)
var y: Float = Float(fPoint.y)
var err: Float = deltaX - deltaY
var sx: Float = -0.5
var sy: Float = -0.5
if fPoint.x < tPoint.x {
sx = 0.5
}
if fPoint.y < tPoint.y {
sy = 0.5
}
repeat {
ret.append(NSValue(cgPoint: CGPoint(x: CGFloat(x), y: CGFloat(y))))
let e: Float = 2 * err
if e > -deltaY {
err -= deltaY
x += sx
}
if e < deltaX {
err += deltaX
y += sy
}
} while round(Float(x)) != round(Float(tPoint.x)) && round(Float(y)) != round(Float(tPoint.y))
ret.append(NSValue(cgPoint: tPoint))
//add final point
return ret
}
func getLocationArrayFrom(startLocation:CLLocation,endLocation:CLLocation)->[CLLocationCoordinate2D]{
var CoordinateArray:[CLLocationCoordinate2D]=[]
如果let points=helperClass.getPointsOnRoute(from:startLocation,to:endLocation,on:mapView){
点对点{
设坐标=点坐标
坐标数组。追加(坐标)
}
}
返回坐标阵列
}
//马克:从电话线上取科迪酸盐
func getPointsOnRoute(从:CLLocation?,到:CLLocation?,在mapView:MKMapView?)->[CLLocation]{
让像素数跳过:Int=120
//数字越小,动画越平滑,但会产生更多层
var ret=[Any]()
var fromPoint:CGPoint?=nil
如果让A坐标=从?坐标{
fromPoint=mapView?转换(坐标、地形点到:mapView)
}
变量拓扑点:CGPoint?=nil
如果让A坐标=至?坐标{
toPoint=mapView?转换(坐标,Topointo:mapView)
}
让allPixels=getAllPoints(from:fromPoint!,to:toPoint!)
变量i=0
而我<(所有像素?.count){
设pointVal=allPixels![i]为?NSValue
ret.append(点(toLocation:mapView,from:(pointVal?.cgPointValue)!)
i+=要跳过的像素数
}
ret.append(点(toLocation:mapView,from:toPoint!))
返回ret as?[CLLocation]
}
/**根据地图视图将CGPoint转换为CLLocation*/
func point(toLocation mapView:MKMapView?,from from point:CGPoint)->CLLocation{
让坐标:CLLocationCoordinate2D?=mapView?转换(从点到坐标从:mapView)
返回CLLocation(纬度:坐标?.纬度0,经度:坐标?.经度0)
}
func getAllPoints(从fPoint:CGPoint到tPoint:CGPoint)->[任何]{
/*Bresenham直线算法的简化实现*/
var ret=[AnyHashable]()
设deltaX:Float=fabsf(Float(tPoint.x-fPoint.x))
设deltaY:Float=fabsf(Float(tPoint.y-fPoint.y))
变量x:Float=Float(fPoint.x)
变量y:Float=Float(fPoint.y)
var err:Float=deltaX-deltaY
变量sx:Float=-0.5
var-sy:Float=-0.5
如果fPoint.x-deltaY{
err-=deltaY
x+=sx
func getLocationArrayFrom(startLocation: CLLocation, endLocation: CLLocation) -> [CLLocationCoordinate2D] {
var coordinatesArray: [CLLocationCoordinate2D] = []
if let points = helperClass.getPointsOnRoute(from: startLocation, to: endLocation, on: mapView) {
for point in points {
let coordinate = point.coordinate
coordinatesArray.append(coordinate)
}
}
return coordinatesArray
}
//MARK: get cordinates from line
func getPointsOnRoute(from: CLLocation?, to: CLLocation?, on mapView: MKMapView?) -> [CLLocation]? {
let NUMBER_OF_PIXELS_TO_SKIP: Int = 120
//lower number will give a more smooth animation, but will result in more layers
var ret = [Any]()
var fromPoint: CGPoint? = nil
if let aCoordinate = from?.coordinate {
fromPoint = mapView?.convert(aCoordinate, toPointTo: mapView)
}
var toPoint: CGPoint? = nil
if let aCoordinate = to?.coordinate {
toPoint = mapView?.convert(aCoordinate, toPointTo: mapView)
}
let allPixels = getAllPoints(from: fromPoint!, to: toPoint!)
var i = 0
while i < (allPixels?.count)! {
let pointVal = allPixels![i] as? NSValue
ret.append(point(toLocation: mapView, from: (pointVal?.cgPointValue)!)!)
i += NUMBER_OF_PIXELS_TO_SKIP
}
ret.append(point(toLocation: mapView, from: toPoint!)!)
return ret as? [CLLocation]
}
/**convert a CGPoint to a CLLocation according to a mapView*/
func point(toLocation mapView: MKMapView?, from fromPoint: CGPoint) -> CLLocation? {
let coord: CLLocationCoordinate2D? = mapView?.convert(fromPoint, toCoordinateFrom: mapView)
return CLLocation(latitude: coord?.latitude ?? 0, longitude: coord?.longitude ?? 0)
}
func getAllPoints(from fPoint: CGPoint, to tPoint: CGPoint) -> [Any]? {
/*Simplyfied implementation of Bresenham's line algoritme */
var ret = [AnyHashable]()
let deltaX: Float = fabsf(Float(tPoint.x - fPoint.x))
let deltaY: Float = fabsf(Float(tPoint.y - fPoint.y))
var x: Float = Float(fPoint.x)
var y: Float = Float(fPoint.y)
var err: Float = deltaX - deltaY
var sx: Float = -0.5
var sy: Float = -0.5
if fPoint.x < tPoint.x {
sx = 0.5
}
if fPoint.y < tPoint.y {
sy = 0.5
}
repeat {
ret.append(NSValue(cgPoint: CGPoint(x: CGFloat(x), y: CGFloat(y))))
let e: Float = 2 * err
if e > -deltaY {
err -= deltaY
x += sx
}
if e < deltaX {
err += deltaX
y += sy
}
} while round(Float(x)) != round(Float(tPoint.x)) && round(Float(y)) != round(Float(tPoint.y))
ret.append(NSValue(cgPoint: tPoint))
//add final point
return ret
}