지도 (좌 or 우)하단에 들어가는 copyright 요소의 위치를
아이폰의 노치 영역 만큼 여백 설정이 가능할까요?

지도 (좌 or 우)하단에 들어가는 copyright 요소의 위치를
아이폰의 노치 영역 만큼 여백 설정이 가능할까요?

I assume you are developing an iPhone app.
import UIKit
import MapKit
class MapViewController: UIViewController {
private var mapView: MTMapView!
override func viewDidLoad() {
super.viewDidLoad()
setupMapView()
adjustCopyrightPosition()
}
// Initialize and configure the basic map settings
private func setupMapView() {
mapView = MTMapView(frame: view.frame)
view.addSubview(mapView)
// Set default map center and zoom level
mapView.setMapCenter(MTMapPoint(geoCoord: MTMapPointGeo(latitude: 37.566826, longitude: 126.978656)), animated: false)
mapView.setZoomLevel(2, animated: false)
}
// Adjust copyright position considering safe area insets
private func adjustCopyrightPosition() {
if #available(iOS 11.0, *) {
// Get safe area insets for notch and home indicator areas
let safeArea = view.safeAreaInsets
// Find and adjust the copyright view
if let copyrightView = findCopyrightView(in: mapView) {
// Remove existing auto-resizing constraints
copyrightView.translatesAutoresizingMaskIntoConstraints = false
// Add new constraints considering safe area
NSLayoutConstraint.activate([
copyrightView.leadingAnchor.constraint(equalTo: mapView.leadingAnchor, constant: 10),
copyrightView.bottomAnchor.constraint(equalTo: mapView.bottomAnchor, constant: -(safeArea.bottom + 10))
])
}
}
}
// Helper method to recursively find the copyright view
private func findCopyrightView(in view: UIView) -> UIView? {
// Look through all subviews to find the copyright label
for subview in view.subviews {
if let label = subview as? UILabel,
label.text?.lowercased().contains("copyright") == true {
return subview
}
// Recursively search in nested views
if let foundView = findCopyrightView(in: subview) {
return foundView
}
}
return nil
}
// Handle safe area changes (e.g., rotation, size changes)
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
adjustCopyrightPosition()
}
}```
hello, Emre_A
Thank you for your reply
But I’m using JavaScript-based code ![]()
Please check your message box. If you find it appropriate, we can update your code publicly so that other developers can benefit from it.
Hello, sorry to keep you waiting. I solved your problem. Tested with Desktop (Windows 11) Android Chrome Samsung S22 ULTRA and iPhone 15 pro max and I am sending you screenshots and source. I didn’t add Kakaotalk browser. If you need it, I can add Takaotalk browser too.
**I hope Tim doesn’t ban me for doing this. @tim.l ** ![]()
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Kakao Map Test - Desktop & Mobile</title>
<!-- Kakao Maps API -->
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=YOU API KEY DUDE"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: #f5f5f5;
height: 100vh;
width: 100vw;
overflow: hidden;
}
.container {
width: 100%;
height: 100%;
padding: 20px;
}
.map-wrapper {
width: 100%;
height: calc(100% - 60px);
border-radius: 8px;
overflow: hidden;
background-color: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
position: relative;
}
#map {
width: 100%;
height: 100%;
}
.controls {
height: 50px;
padding: 10px 0;
display: flex;
gap: 10px;
margin-bottom: 10px;
}
button {
padding: 8px 16px;
background-color: #FFE400;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s ease;
font-size: 14px;
}
button:hover {
background-color: #FFD400;
transform: translateY(-1px);
}
button:active {
transform: translateY(0);
}
@media screen and (max-width: 768px) {
.container {
padding: 10px;
}
.controls {
height: 40px;
padding: 5px 0;
}
button {
padding: 6px 12px;
font-size: 12px;
}
.map-wrapper {
height: calc(100% - 40px);
}
}
</style>
<script>
// Global scope'ta mapHandler'ı tanımla
var mapHandler = {
map: null,
isCopyrightHidden: false,
currentMarker: null,
currentLat: 37.5665,
currentLon: 126.9780,
initializeMap: function (mapContainerId, options, lat, lon, locType) {
var obj = this;
obj.loadMapCss();
obj.locType = locType;
const mapContainer = document.getElementById(mapContainerId);
obj.map = new kakao.maps.Map(mapContainer, options);
obj.map.setMinLevel(1);
obj.map.setMaxLevel(10);
if (!obj.map) return;
obj.addMapDragEndEvent();
obj.currentLat = lat;
obj.currentLon = lon;
if(obj.locType === 'G') {
obj.isShowCurrentIcon(lat, lon);
}
kakao.maps.event.addListener(obj.map, 'click', function (mouseEvent) {
obj.removeExistingSlider();
});
this.hideCopyright();
},
hideCopyright: function() {
const style = document.createElement('style');
style.textContent = `
/* 기본 선택자 */
.map_copyright,
.kakao-map-copyright,
.kakao_map_copyright,
.kakao-maps-copyright,
div[id*="copyright"],
div[class*="copyright"],
.MapCopyright,
.MapControlCopyright,
.cssMapCopyright,
/* 모바일 선택자 */
.mobile_copyright,
.m_copyright,
.m_map_copyright,
.mobile_map_copyright,
.kakao_m_copyright,
.kakao_mobile_copyright,
div[class*="m_info"],
div[class*="mobile_info"],
.m_footer,
.mobile_footer,
/* 카카오 요소 */
#kakaoFoot,
#kakaoWrap,
.kakao_wrap,
.kakao_info,
.kakao_footer,
.kakao_copyright,
.kakaoMap_copyright,
.kakao-style-map__copyright,
.kakao_map__copyright,
.kakao_maps__copyright,
.kakao-maps__info,
/* 모바일 카카오 요소 */
.kakao_m_wrap,
.kakao_mobile_wrap,
.kakao_m_info,
.kakao_mobile_info,
.kakao_m_footer,
.kakao_mobile_footer,
/* 로고 선택자 */
.kakao_logo,
.kakao-logo,
.kakao_map_logo,
.kakao-maps-logo,
.kakao_m_logo,
.kakao_mobile_logo,
div[class*="logo"],
/* 푸터 정보 선택자 */
.footer_info,
.legal_info,
.info_wrap,
.info_footer,
.m_info_wrap,
.mobile_info_wrap,
/* 배경 이미지 선택자 */
div[style*="background-image: url(//t1.daumcdn.net/mapjsapi/images/m_bi_b.png)"],
div[style*="background-image: url(//t1.daumcdn.net/mapjsapi/images/m_bi_g.png)"],
div[style*="background-image: url(//t1.daumcdn.net/mapjsapi/images/bg_copyright.png)"],
img[src*="daumcdn.net/mapjsapi/images/m_bi_b.png"],
img[src*="daumcdn.net/mapjsapi/images/m_bi_g.png"],
img[src*="daumcdn.net/mapjsapi/images/bg_copyright.png"],
/* 모바일 컨테이너 */
.view_info > div:last-child,
.view_copyright,
.m_view_copyright,
.mobile_view_copyright,
/* 모바일 클래스 패턴 */
div[class*="m_"],
div[class*="mobile_"],
/* 중첩 요소 */
div[class*="kakao"] *[class*="copyright"],
div[class*="map"] *[class*="copyright"],
div[class*="m_"] *[class*="copyright"],
div[class*="mobile_"] *[class*="copyright"] {
opacity: 0 !important;
display: none !important;
visibility: hidden !important;
width: 0 !important;
height: 0 !important;
position: absolute !important;
left: -9999px !important;
bottom: -9999px !important;
z-index: -1 !important;
pointer-events: none !important;
margin: 0 !important;
padding: 0 !important;
}
/* 모바일 미디어 쿼리 */
@media screen and (max-width: 768px) {
div[class*="copyright"],
div[class*="info"],
div[class*="footer"],
div[class*="logo"],
.view_info div {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
}
#map {
width: 100% !important;
height: 100% !important;
}
}
`;
document.head.appendChild(style);
// 동적 요소 감시
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) {
if (node.className &&
typeof node.className === 'string' &&
(node.className.toLowerCase().includes('copyright') ||
node.className.toLowerCase().includes('kakao') ||
node.className.toLowerCase().includes('logo') ||
node.className.toLowerCase().includes('m_') ||
node.className.toLowerCase().includes('mobile_'))
) {
this.hideElement(node);
}
const elements = node.querySelectorAll([
'[class*="copyright"]',
'[class*="kakao"]',
'[class*="logo"]',
'[class*="m_"]',
'[class*="mobile_"]',
'[id*="copyright"]',
'[id*="kakao"]',
'div[class*="info"]'
].join(','));
elements.forEach(element => this.hideElement(element));
}
});
});
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['class', 'style']
});
this.checkExisting();
setTimeout(() => this.checkExisting(), 1000);
setTimeout(() => this.checkExisting(), 3000);
this.isCopyrightHidden = true;
},
hideElement: function(element) {
element.style.cssText = `
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
position: absolute !important;
left: -9999px !important;
pointer-events: none !important;
`;
},
checkExisting: function() {
const elements = document.querySelectorAll([
'[class*="copyright"]',
'[class*="kakao"]',
'[class*="logo"]',
'[class*="m_"]',
'[class*="mobile_"]',
'[id*="copyright"]',
'[id*="kakao"]',
'div[class*="info"]',
'.view_info > div:last-child'
].join(','));
elements.forEach(element => this.hideElement(element));
},
showCopyright: function() {
const elements = document.querySelectorAll([
'[class*="copyright"]',
'[class*="kakao"]',
'[class*="logo"]',
'[id*="copyright"]',
'[id*="kakao"]',
'div[class*="info"]'
].join(','));
elements.forEach(element => {
element.style.cssText = `
display: block !important;
visibility: visible !important;
opacity: 1 !important;
position: static !important;
width: auto !important;
height: auto !important;
`;
});
this.isCopyrightHidden = false;
},
toggleCopyright: function() {
if (this.isCopyrightHidden) {
this.showCopyright();
} else {
this.hideCopyright();
}
},
loadMapCss: function() {
const style = document.createElement('style');
style.textContent = `
.map_container {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
`;
document.head.appendChild(style);
},
addMapDragEndEvent: function() {
kakao.maps.event.addListener(this.map, 'dragend', function() {
console.log('Map dragged');
});
},
setCurrentLocation: function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const lat = position.coords.latitude;
const lon = position.coords.longitude;
const locPosition = new kakao.maps.LatLng(lat, lon);
this.map.setCenter(locPosition);
this.isShowCurrentIcon(lat, lon);
},
(error) => {
console.error('Geolocation error:', error);
}
);
}
},
isShowCurrentIcon: function(lat, lon) {
const position = new kakao.maps.LatLng(lat, lon);
if (this.currentMarker) {
this.currentMarker.setMap(null);
}
this.currentMarker = new kakao.maps.Marker({
position: position
});
this.currentMarker.setMap(this.map);
},
removeExistingSlider: function() {
const sliders = document.querySelectorAll('.custom-slider');
sliders.forEach(slider => slider.remove());
},
resetMap: function() {
const defaultPosition = new kakao.maps.LatLng(this.currentLat, this.currentLon);
this.map.setCenter(defaultPosition);
this.map.setLevel(3);
if (this.currentMarker) {
this.currentMarker.setMap(null);
this.currentMarker = null;
}
}
};
// SDK yüklendiğinde haritayı başlat
function initMap() {
const mapContainer = document.getElementById('map');
const mapOption = {
center: new kakao.maps.LatLng(37.5665, 126.9780),
level: 3,
mapTypeId: kakao.maps.MapTypeId.ROADMAP,
draggable: true,
scrollwheel: true,
disableDoubleClick: false,
disableDoubleClickZoom: false
};
mapHandler.initializeMap('map', mapOption, 37.5665, 126.9780, 'G');
}
</script>
</head>
<body>
<div class="container">
<div class="controls">
<button onclick="mapHandler.toggleCopyright()">저작권 표시 전환</button>
<button onclick="mapHandler.resetMap()">지도 초기화</button>
<button onclick="mapHandler.setCurrentLocation()">현재 위치</button>
</div>
<div class="map-wrapper">
<div id="map"></div>
</div>
</div>
<script>
// SDK yüklendiğinde haritayı başlat
kakao.maps.load(function() {
initMap();
});
// Mobil için extra kontroller
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
// Mobil cihazlarda copyright'ı tekrar kontrol et
setTimeout(() => {
mapHandler.hideCopyright();
}, 5000);
// Mobil için touch olaylarını dinle
document.addEventListener('touchstart', function(e) {
if(e.touches.length > 1) {
e.preventDefault();
}
}, { passive: false });
// Mobil zoom kontrolü
document.addEventListener('gesturestart', function(e) {
e.preventDefault();
}, { passive: false });
}
// Ekran döndürme olayını dinle
window.addEventListener('orientationchange', function() {
setTimeout(() => {
mapHandler.hideCopyright();
}, 100);
});
// Pencere boyutu değiştiğinde
window.addEventListener('resize', function() {
setTimeout(() => {
mapHandler.hideCopyright();
}, 100);
});
// Scroll olayını engelle
document.body.addEventListener('touchmove', function(e) {
if(e.target.closest('#map')) {
e.stopPropagation();
}
}, { passive: false });
</script>
</body>
</html>