我想要一个可以无限上下移动图像的动画。但是,当我运行代码时,动画仅发生一次。这是动画 xml: 我想要一个可以无限上下移动图像的动画。但是,当我运行代码时,动画仅发生一次。这是动画 xml: <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/linear_interpolator" android:repeatCount="3" android:repeatMode="restart"> <!-- move down --> <translate android:fromYDelta="0%" android:toYDelta="50%" android:duration="1500" android:fillAfter="true"/> <!-- move up --> <translate android:fromYDelta="0%" android:startOffset="1500" android:toYDelta="-50%" android:duration="1500" android:fillAfter="true"/> <!-- continue to move up --> <translate android:fromYDelta="0%" android:startOffset="3000" android:toYDelta="-20%" android:duration="600" android:fillAfter="true"/> <!-- down to original pos --> <translate android:fromYDelta="0%" android:startOffset="3600" android:toYDelta="20%" android:duration="600" android:fillAfter="true"/> </set> 这是我的java代码: public class MainActivity extends AppCompatActivity { Animation move1, move2, move3, move4, move5; Button login; ImageView bar1, bar2, bar3, bar4, bar5; int delay1 = 500; int delay2 = 1560; int delay3 = 2300; int delay4 = 3065; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); login = findViewById(R.id.btLogin); bar1 = findViewById(R.id.ivBar1); bar2 = findViewById(R.id.ivBar2); bar3 = findViewById(R.id.ivBar3); bar4 = findViewById(R.id.ivBar4); bar5 = findViewById(R.id.ivBar5); move1= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move); move2= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move); move3= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move); move4= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move); move5= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move); bar1.startAnimation(move1); Handler handler = new Handler(); handler.postDelayed(() -> bar2.startAnimation(move2), delay1); handler.postDelayed(() -> bar3.startAnimation(move3), delay2); handler.postDelayed(() -> bar4.startAnimation(move4), delay3); handler.postDelayed(() -> bar5.startAnimation(move5), delay4); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); } } 为什么它不无限重复?和xml中的fill-after属性有关系吗?非常感谢您的帮助,这是一个班级项目。 从动画 XML 中删除 android:fillAfter="true",并在父 android:repeatCount="infinite" 标记中设置 <set>,而不是 repeatCount="3"。 fillAfter 使每个动画保持其最终状态,防止正确循环。 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/linear_interpolator" android:repeatCount="infinite" android:repeatMode="restart"> <!-- move down --> <translate android:fromYDelta="0%" android:toYDelta="50%" android:duration="1500"/> <!-- move up --> <translate android:fromYDelta="50%" android:startOffset="1500" android:toYDelta="-50%" android:duration="1500"/> <!-- continue to move up --> <translate android:fromYDelta="-50%" android:startOffset="3000" android:toYDelta="-20%" android:duration="600"/> <!-- down to original pos --> <translate android:fromYDelta="-20%" android:startOffset="3600" android:toYDelta="0%" android:duration="600"/> </set> 这就是让它无限循环所需的全部。
我有以下SVG;它类似于字母“P”。我想用黑色填充整个“P”,但要逐渐地遵循绘图的流程,就像正在绘制一样。 我有以下SVG;它类似于字母“P”。我想用黑色填充整个“P”,但要逐渐地遵循绘图的流程,就像正在绘制一样。 <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> <g stroke="#000" stroke-width="1" fill="none"> <path d="M31.5294 14.2118C31.5294 18.8819 28.7623 22.9082 24.7793 24.7351C26.4612 23.3496 27.5322 21.248 27.5322 18.896C27.5322 14.7642 24.2259 11.4042 20.112 11.3205C20.0574 11.3167 20.0075 11.3167 19.9529 11.3167C19.8983 11.3167 19.8485 11.3167 19.7939 11.3205C18.2673 11.4033 17.0588 12.6663 17.0588 14.2108V28.6814C17.0588 33.4748 13.1699 37.3638 8.37646 37.3638V14.2118C8.37646 7.81928 13.5605 2.63528 19.9529 2.63528C26.3454 2.63528 31.5294 7.81928 31.5294 14.2118Z"/> </g> </svg> 如果我只是从下到上或从左到右填充,其他类似问题的解决方案,它不会遵循绘制时的“P”形状。请注意:我对 SVG 没有太多专业知识。 我举了一个例子来说明如何做到这一点。我知道这可能不完全是您想要的,但这说明了一条可以遵循的道路。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="style.css"> </head> <body> <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> <style> @keyframes fade-in-right { from { clip-path: circle(0px); } to { clip-path: circle(40px); } } #path2 { animation: fade-in-right ease 4s infinite; } </style> <g stroke="#000000" stroke-width="1" fill="none" id="g1"> <path d="m 31.5294,14.2118 c 0,4.6701 -2.7671,8.6964 -6.7501,10.5233 1.6819,-1.3855 2.7529,-3.4871 2.7529,-5.8391 0,-4.1318 -3.3063,-7.4918 -7.4202,-7.5755 -0.0546,-0.0038 -0.1045,-0.0038 -0.1591,-0.0038 -0.0546,0 -0.1044,0 -0.159,0.0038 -1.5266,0.0828 -2.7351,1.3458 -2.7351,2.8903 v 14.4706 c 0,4.7934 -3.8889,8.6824 -8.68234,8.6824 v -23.152 c 0,-6.39252 5.18404,-11.57652 11.57644,-11.57652 6.3925,0 11.5765,5.184 11.5765,11.57652 z" id="path1" /> </g> <g stroke="#000000" stroke-width="1" fill="none" id="g2"> <path d="m 31.5294,14.2118 c 0,4.6701 -2.7671,8.6964 -6.7501,10.5233 1.6819,-1.3855 2.7529,-3.4871 2.7529,-5.8391 0,-4.1318 -3.3063,-7.4918 -7.4202,-7.5755 -0.0546,-0.0038 -0.1045,-0.0038 -0.1591,-0.0038 -0.0546,0 -0.1044,0 -0.159,0.0038 -1.5266,0.0828 -2.7351,1.3458 -2.7351,2.8903 v 14.4706 c 0,4.7934 -3.8889,8.6824 -8.68234,8.6824 v -23.152 c 0,-6.39252 5.18404,-11.57652 11.57644,-11.57652 6.3925,0 11.5765,5.184 11.5765,11.57652 z" id="path2" style="fill:#000000;fill-opacity:1;stroke:none" /> </g> </svg> </body> </html>
我决定通过创建挪威夏季的公路旅行地图来开始学习 Leaflet 和 JavaScript,这是我的项目的可重复示例: 我决定通过创建挪威夏季的公路旅行地图来开始学习 Leaflet 和 JavaScript,这是我的项目的可重复示例: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" /> <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/slick/slick.css"/> <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/slick/slick-theme.css"/> <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js"></script> <link rel="stylesheet" href="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.css" /> <script src="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.js"></script> <style> body { margin: 0; } #map { width: 100%; height: 100vh; } .carousel { max-width: 300px; margin: 10px auto; } .carousel img { width: 100%; height: auto; } /* Custom styling for Geiranger popup content */ .geiranger-popup-content { max-width: 500px; padding: 20px; } </style> </head> <body> <div id="map"></div> <script> var map = L.map('map').setView([61.9241, 6.7527], 6); var streetViewMarker = null; // Variable to keep track of the Street View marker L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); var roadTripCoordinates = [ [59.9139, 10.7522], // Oslo [62.2622, 10.7654], // Tynset [62.5949, 9.6926], // Oppdal [63.0071, 7.2058], // Atlantic Road [62.1040, 7.2054] // Geiranger ]; // Function to initialize Slick Carousel for a specific marker function initSlickCarousel(markerId, images) { $(`#${markerId}_carousel`).slick({ infinite: true, slidesToShow: 1, slidesToScroll: 1, dots: true, arrows: true }); // Add images to the carousel images.forEach(img => { $(`#${markerId}_carousel`).slick('slickAdd', `<div><img src="${img}" alt="Image"></div>`); }); } // Add markers for each destination with additional information and multiple pictures var destinations = [ { coordinates: [59.9139, 10.7522], name: 'Oslo', info: "../07/2023 : Start of the road-trip", images: ['https://www.ecologie.gouv.fr/sites/default/files/styles/standard/public/Oslo%2C%20Norvege_AdobeStock_221885853.jpeg?itok=13d8oQbU', 'https://via.placeholder.com/300', 'https://via.placeholder.com/300'] }, { coordinates: [62.2622, 10.7654], name: 'Tynset', info: "../07/2023 : Fly-fishing spot 1", images: ['https://www.czechnymph.com/data/web/gallery/fisheries/norway/glommahein/Kvennan_Fly_Fishing_20.jpg', 'https://via.placeholder.com/300', 'https://via.placeholder.com/300'] }, { coordinates: [62.5949, 9.6926], name: 'Oppdal', info: "../07/2023 : Awesome van spot for the night", images: ['https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFRtpLlHWr8j6S2jNStnq6_Z9qBe0jWuFH8Q&usqp=CAU', 'https://via.placeholder.com/300', 'https://via.placeholder.com/300'] }, { coordinates: [63.0071, 7.2058], name: 'Atlantic Road', info: "../07/2023 : Fjord fishing", images: ['https://images.locationscout.net/2021/04/atlantic-ocean-road-norway.jpg?h=1100&q=83', 'https://via.placeholder.com/300', 'https://via.placeholder.com/300'] }, { coordinates: [62.1040, 7.2054], name: 'Geiranger', info: "../07/2023 : Hiking 1", images: ['https://www.fjordtours.com/media/10968/nicola_montaldo-instagram-26th-may-2021-0717-utc.jpeg?anchor=center&mode=crop&width=1120&height=1120&rnd=133209254300000000&slimmage=True', 'https://via.placeholder.com/300', 'https://via.placeholder.com/300'] } ]; // Use Leaflet Routing Machine with Mapbox Routing plugin to get and display the route L.Routing.control({ waypoints: roadTripCoordinates.map(coord => L.latLng(coord[0], coord[1])), router: L.Routing.mapbox('MAP_BOX_KEY'), draggableWaypoints: false, addWaypoints: false, lineOptions: { styles: [{ color: 'brown', opacity: 0.7, weight: 2 }] } }).addTo(map); // Remove the leaflet-routing-container from the DOM var routingContainer = document.querySelector('.leaflet-routing-container'); if (routingContainer) { routingContainer.parentNode.removeChild(routingContainer); } destinations.forEach(function (destination) { var marker = L.marker(destination.coordinates).addTo(map); var markerId = destination.name.replace(' ', '_'); marker.bindPopup(` <b>${destination.name}</b><br> ${destination.info}<br> <div class="carousel" id="${markerId}_carousel"></div> `).on('popupopen', function () { // Initialize Slick Carousel when the marker popup is opened initSlickCarousel(markerId, destination.images); }).openPopup(); }); // Add Street View panorama on map click map.on('click', function (e) { if (streetViewMarker) { // Remove the existing Street View marker map.removeLayer(streetViewMarker); } let lat = e.latlng.lat.toPrecision(8); let lon = e.latlng.lng.toPrecision(8); streetViewMarker = L.marker([lat, lon]).addTo(map) .bindPopup(`<a href="http://maps.google.com/maps?q=&layer=c&cbll=${lat},${lon}&cbp=11,0,0,0,0" target="blank"><b> Cliquer ici pour avoir un aperçu de la zone ! </b></a>`).openPopup(); }); </script> </body> </html> 一切都按预期进行,我不得不说我对渲染非常满意。然而,通过查看 Stackoverflow 上的不同主题,我发现可以通过单击地图来显示 Google 街景视图。这个功能真的很酷,但我想限制仅在我的公路旅行行程中添加街景标记的选项。 有人可以帮我吗? 您通过创建挪威夏季公路旅行地图开始了学习 Leaflet 和 JavaScript 的旅程,真是太棒了。到目前为止,您的项目设置看起来不错,我很乐意在您的进展过程中提供指导或帮助。 既然您已经包含了 Leaflet、Slick Carousel 和 Leaflet Routing Machine 库,看来您正计划使用 Slick Carousel 创建一个带有路线的交互式地图,也许还有一些附加功能。 以下是一些增强您的项目的建议: 地图初始化: 使用初始视图和要显示的任何特定标记或图层设置您的传单地图。 路由功能: 利用 Leaflet Routing Machine 将动态路线添加到您的地图。您可以自定义路线、添加航点并提供逐向指示。 照片轮播: 既然您提到了公路旅行地图,请考虑集成 Slick Carousel 来展示旅途中关键地点的照片或描述。这可以为您的地图添加视觉上吸引人的元素。 地图控制: 探索 Leaflet 插件或内置控件以增强用户体验。例如,您可以添加缩放控件或比例尺。 响应式设计: 确保您的地图能够响应不同的设备。 Leaflet 通常适合移动设备,但如果需要的话进行测试和调整是一个很好的做法。 数据层: 如果您有与您的公路旅行相关的特定数据点或事件,您可以使用标记或其他视觉元素在地图上表示它们。 JavaScript 交互性: 使用 JavaScript 为地图添加交互性。对于 ㅤ 实例,当用户单击标记时,您可以创建包含附加信息的弹出窗口。 记得迭代测试你的项目,并参考每个库的文档以获取详细的使用说明。 如果您有具体问题或在此过程中遇到挑战,请随时提问。祝您的公路旅行地图项目好运!