From 5fad3a8ce445749f3c0dc68d6cbf9385c10560a3 Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Tue, 27 Oct 2026 02:08:51 -0700 Subject: [PATCH] Center a side label on the pin, not on its head With the label beside the pin (left / right), center lined it up with the head's center, 0.35 of the icon down, so it sat well above the middle of the pin and did not look centered. It is now halfway between the pin's top and its tip, midway between top and bottom. center center and the labels above or below are unchanged. Same change as js-sdk-core#11. --- .../marker/ColorDefaultIcon.swift | 6 ++++-- .../DefaultIconLabelPositionTests.swift | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Sources/MapConductorCore/marker/ColorDefaultIcon.swift b/Sources/MapConductorCore/marker/ColorDefaultIcon.swift index 8b12432..2202d48 100644 --- a/Sources/MapConductorCore/marker/ColorDefaultIcon.swift +++ b/Sources/MapConductorCore/marker/ColorDefaultIcon.swift @@ -34,7 +34,7 @@ public final class ColorDefaultIcon: MarkerIconProtocol { /// ラベルをピンに対してどこへ置くか。CSS の `background-position` と同じ書き方で、 /// 横(left / center / right)と縦(top / center / bottom)のキーワードを空白区切りで /// 並べる。順序は問わず、片方だけなら残りは center。 - /// - left / right はピンの外側に置き、縦はピンの上端・頭の中心・先端に揃える。 + /// - left / right はピンの外側に置き、縦はピンの上端・上端と先端の中間・先端に揃える。 /// - center 列の top / bottom はピンの上・下の外側に置く。 public let labelPosition: String /// 指定された infoAnchor(ピン本体に対する割合)。`infoAnchor` はビットマップに対する割合へ直した値。 @@ -539,9 +539,11 @@ struct DefaultIconLayout { var cy = headCenterY if h != 0 { - // 横に置くときは、縦はピンの上端・頭の中心・先端に揃える。 + // 横に置くときは、縦はピンの上端・上端と先端の中間・先端に揃える。 + // center を頭の中心にすると、ピン全体の中央より上に見える。 if v < 0 { cy = pinTop + labelHeight / 2.0 } if v > 0 { cy = pinBottom - labelHeight / 2.0 } + if v == 0 { cy = (pinTop + pinBottom) / 2.0 } } else { // 中央列の top / bottom はピンと重ならないよう上下の外側に置く。 if v < 0 { cy = pinTop - gap - labelHeight / 2.0 } diff --git a/Tests/MapConductorCoreTests/DefaultIconLabelPositionTests.swift b/Tests/MapConductorCoreTests/DefaultIconLabelPositionTests.swift index 0cc193a..fa02e40 100644 --- a/Tests/MapConductorCoreTests/DefaultIconLabelPositionTests.swift +++ b/Tests/MapConductorCoreTests/DefaultIconLabelPositionTests.swift @@ -41,6 +41,21 @@ final class DefaultIconLabelPositionTests: XCTestCase { XCTAssertEqual(icon.anchor, icon.toBitmapIcon().anchor) } + func testSideCenterIsHalfwayDownThePin() { + // 横に置いた center は、ピンの上端と先端の真ん中(頭の中心ではない)。 + let metrics = DefaultMarkerIcon.markerPathMetrics(canvasSize: 48, iconScale: 1, strokeWidth: 1) + let middle = metrics.offsetY + 12.0 * metrics.markerScale + for position in ["right center", "left center", "right"] { + let layout = DefaultIconLayout.make( + canvasSize: 48, iconScale: 1, strokeWidth: 1, + labelSize: CGSize(width: 60, height: 16), outlineStrokeWidth: 2, + labelPosition: position + ) + XCTAssertEqual(layout.labelCenter.y - layout.markerOffsetY, middle, accuracy: 0.001, position) + XCTAssertGreaterThan(middle, 48 * 0.35 + 3, "the head's center is well above the middle") + } + } + func testLeftIsNearlyMirrorOfRight() { // ピン形は外接箱の中で 0.25 単位だけ右に寄っているので、1pt までの差は許す。 let right = tip(ColorDefaultIcon(label: label, labelPosition: "right"))