[{"data":1,"prerenderedAt":1666},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fautomating-atlas-map-series\u002Fhighlight-atlas-feature-in-overview-map-pyqgis":3},{"id":4,"title":5,"body":6,"description":1655,"extension":1656,"meta":1657,"navigation":187,"path":1662,"seo":1663,"stem":1664,"__hash__":1665},"docs\u002Fspatial-data-processing-automation\u002Fautomating-atlas-map-series\u002Fhighlight-atlas-feature-in-overview-map-pyqgis\u002Findex.md","Highlight the Atlas Feature in an Overview Map in PyQGIS",{"type":7,"value":8,"toc":1641},"minimark",[9,13,17,26,120,125,140,144,147,425,432,436,439,505,723,740,744,747,906,916,920,923,1124,1138,1142,1145,1264,1277,1281,1284,1369,1482,1494,1498,1512,1516,1553,1557,1563,1567,1573,1585,1591,1597,1603,1607,1637],[10,11,5],"h1",{"id":12},"highlight-the-atlas-feature-in-an-overview-map-in-pyqgis",[14,15,16],"p",{},"An atlas page that shows one district at large scale answers \"what is here?\" but not \"where is this?\". Two techniques fix that: an overview map — a small map of the whole area with a frame marking the current page — and a style on the main map that makes the current feature stand out from its neighbours. Both rely on atlas variables, which QGIS updates for every page, so a single style or overview definition serves the whole series.",[14,18,19,20,25],{},"This recipe belongs to ",[21,22,24],"a",{"href":23},"\u002Fspatial-data-processing-automation\u002Fautomating-atlas-map-series\u002F","Automating Atlas Map Series",". It adds an overview map with an extent frame, highlights the current feature and dims others with a rule-based style, masks everything outside the current feature, labels only the current feature, and checks the result in exports.",[14,27,28],{},[29,30,35,39,43,50,59,69,77,83,86,92,96,99,102,105,114],"svg",{"viewBox":31,"role":32,"ariaLabel":33,"xmlns":34},"0 0 760 290","img","An atlas page with a main map highlighting the current district and an overview map framing its position in the region","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[36,37,38],"title",{},"An atlas page that says where it is",[40,41,42],"desc",{},"The main map shows the current district at large scale with its neighbours dimmed and the current district outlined boldly. A small overview map in the corner shows the whole region, with all districts in grey and a red frame marking the extent of the main map. Both update automatically on every atlas page.",[44,45],"rect",{"x":46,"y":46,"width":47,"height":48,"fill":49},"0","760","290","#f6f3ea",[51,52,58],"text",{"x":53,"y":54,"style":55,"fill":56,"textAnchor":57},"380","28","text-anchor:middle;font-size:14px;font-family:sans-serif;font-weight:bold","#17211d","middle","Main map for detail, overview for context",[44,60],{"x":61,"y":62,"width":63,"height":64,"rx":65,"fill":66,"stroke":67,"style":68},"40","52","460","220","4","#fffdf7","#59645f","stroke-width:1.5",[70,71],"polygon",{"points":72,"fill":73,"fillOpacity":74,"stroke":75,"style":76},"80,80 220,70 240,180 100,200","#f0ebdd",0.85,"#b8b1a0","stroke-width:1",[70,78],{"points":79,"fill":80,"fillOpacity":74,"stroke":81,"style":82},"220,70 420,90 440,230 240,180","#eef7f4","#0f766e","stroke-width:3",[70,84],{"points":85,"fill":73,"fillOpacity":74,"stroke":75,"style":76},"100,200 240,180 260,260 90,262",[51,87,91],{"x":88,"y":89,"style":90,"fill":81,"textAnchor":57},"330","160","text-anchor:middle;font-size:11.0px;font-family:sans-serif;font-weight:bold","current district",[44,93],{"x":94,"y":62,"width":95,"height":89,"rx":65,"fill":66,"stroke":67,"style":68},"530","200",[70,97],{"points":98,"fill":73,"fillOpacity":74,"stroke":75,"style":76},"550,70 620,64 640,120 560,130",[70,100],{"points":101,"fill":73,"fillOpacity":74,"stroke":75,"style":76},"620,64 700,72 712,140 640,120",[70,103],{"points":104,"fill":73,"fillOpacity":74,"stroke":75,"style":76},"560,130 640,120 650,196 552,198",[44,106],{"x":107,"y":108,"width":109,"height":110,"rx":46,"fill":111,"stroke":112,"style":113},"615","60","100","85","none","#b91c1c","stroke-width:2.5",[51,115,119],{"x":116,"y":117,"style":118,"fill":112,"textAnchor":57},"630","236","text-anchor:middle;font-size:10.5px;font-family:sans-serif","overview with extent frame",[121,122,124],"h2",{"id":123},"prerequisites","Prerequisites",[126,127,128,132],"ul",{},[129,130,131],"li",{},"QGIS 3.34 LTR or newer, or the QGIS 4 series.",[129,133,134,135,139],{},"A layout with an atlas and an atlas-driven main map, as set up in ",[21,136,138],{"href":137},"\u002Fspatial-data-processing-automation\u002Fautomating-atlas-map-series\u002Fconfigure-atlas-coverage-layer-pyqgis\u002F","configuring an atlas coverage layer",".",[121,141,143],{"id":142},"add-an-overview-map-with-an-extent-frame","Add an overview map with an extent frame",[14,145,146],{},"An overview is a second map item showing the whole area at a fixed extent, with an overview frame linked to the main map. The frame moves with the main map on every page.",[148,149,154],"pre",{"className":150,"code":151,"language":152,"meta":153,"style":153},"language-python shiki shiki-themes github-dark","from qgis.core import (QgsProject, QgsLayoutItemMap, QgsLayoutItemMapOverview, QgsLayoutPoint,\n                       QgsLayoutSize, QgsUnitTypes, QgsFillSymbol)\n\nlayout = QgsProject.instance().layoutManager().layoutByName(\"District atlas\")\nmain_map = layout.itemById(\"main_map\")\natlas = layout.atlas()\ncoverage = atlas.coverageLayer()\n\noverview = QgsLayoutItemMap(layout)\noverview.setId(\"overview_map\")\noverview.attemptMove(QgsLayoutPoint(222, 12, QgsUnitTypes.LayoutMillimeters))\noverview.attemptResize(QgsLayoutSize(62, 48, QgsUnitTypes.LayoutMillimeters))\noverview.setLayers([coverage])\noverview.setKeepLayerSet(True)\noverview.zoomToExtent(coverage.extent())\noverview.setFrameEnabled(True)\nlayout.addLayoutItem(overview)\n\nframe = QgsLayoutItemMapOverview(\"current page\", overview)\nframe.setLinkedMap(main_map)\nframe.setFrameSymbol(QgsFillSymbol.createSimple(\n    {\"color\": \"255,0,0,0\", \"outline_color\": \"#b91c1c\", \"outline_width\": \"0.6\"}))\noverview.overviews().addOverview(frame)\n","python","",[155,156,157,176,182,189,208,224,235,246,251,262,273,292,308,314,325,331,341,347,352,369,375,381,419],"code",{"__ignoreMap":153},[158,159,162,166,170,173],"span",{"class":160,"line":161},"line",1,[158,163,165],{"class":164},"snl16","from",[158,167,169],{"class":168},"s95oV"," qgis.core ",[158,171,172],{"class":164},"import",[158,174,175],{"class":168}," (QgsProject, QgsLayoutItemMap, QgsLayoutItemMapOverview, QgsLayoutPoint,\n",[158,177,179],{"class":160,"line":178},2,[158,180,181],{"class":168},"                       QgsLayoutSize, QgsUnitTypes, QgsFillSymbol)\n",[158,183,185],{"class":160,"line":184},3,[158,186,188],{"emptyLinePlaceholder":187},true,"\n",[158,190,192,195,198,201,205],{"class":160,"line":191},4,[158,193,194],{"class":168},"layout ",[158,196,197],{"class":164},"=",[158,199,200],{"class":168}," QgsProject.instance().layoutManager().layoutByName(",[158,202,204],{"class":203},"sU2Wk","\"District atlas\"",[158,206,207],{"class":168},")\n",[158,209,211,214,216,219,222],{"class":160,"line":210},5,[158,212,213],{"class":168},"main_map ",[158,215,197],{"class":164},[158,217,218],{"class":168}," layout.itemById(",[158,220,221],{"class":203},"\"main_map\"",[158,223,207],{"class":168},[158,225,227,230,232],{"class":160,"line":226},6,[158,228,229],{"class":168},"atlas ",[158,231,197],{"class":164},[158,233,234],{"class":168}," layout.atlas()\n",[158,236,238,241,243],{"class":160,"line":237},7,[158,239,240],{"class":168},"coverage ",[158,242,197],{"class":164},[158,244,245],{"class":168}," atlas.coverageLayer()\n",[158,247,249],{"class":160,"line":248},8,[158,250,188],{"emptyLinePlaceholder":187},[158,252,254,257,259],{"class":160,"line":253},9,[158,255,256],{"class":168},"overview ",[158,258,197],{"class":164},[158,260,261],{"class":168}," QgsLayoutItemMap(layout)\n",[158,263,265,268,271],{"class":160,"line":264},10,[158,266,267],{"class":168},"overview.setId(",[158,269,270],{"class":203},"\"overview_map\"",[158,272,207],{"class":168},[158,274,276,279,283,286,289],{"class":160,"line":275},11,[158,277,278],{"class":168},"overview.attemptMove(QgsLayoutPoint(",[158,280,282],{"class":281},"sDLfK","222",[158,284,285],{"class":168},", ",[158,287,288],{"class":281},"12",[158,290,291],{"class":168},", QgsUnitTypes.LayoutMillimeters))\n",[158,293,295,298,301,303,306],{"class":160,"line":294},12,[158,296,297],{"class":168},"overview.attemptResize(QgsLayoutSize(",[158,299,300],{"class":281},"62",[158,302,285],{"class":168},[158,304,305],{"class":281},"48",[158,307,291],{"class":168},[158,309,311],{"class":160,"line":310},13,[158,312,313],{"class":168},"overview.setLayers([coverage])\n",[158,315,317,320,323],{"class":160,"line":316},14,[158,318,319],{"class":168},"overview.setKeepLayerSet(",[158,321,322],{"class":281},"True",[158,324,207],{"class":168},[158,326,328],{"class":160,"line":327},15,[158,329,330],{"class":168},"overview.zoomToExtent(coverage.extent())\n",[158,332,334,337,339],{"class":160,"line":333},16,[158,335,336],{"class":168},"overview.setFrameEnabled(",[158,338,322],{"class":281},[158,340,207],{"class":168},[158,342,344],{"class":160,"line":343},17,[158,345,346],{"class":168},"layout.addLayoutItem(overview)\n",[158,348,350],{"class":160,"line":349},18,[158,351,188],{"emptyLinePlaceholder":187},[158,353,355,358,360,363,366],{"class":160,"line":354},19,[158,356,357],{"class":168},"frame ",[158,359,197],{"class":164},[158,361,362],{"class":168}," QgsLayoutItemMapOverview(",[158,364,365],{"class":203},"\"current page\"",[158,367,368],{"class":168},", overview)\n",[158,370,372],{"class":160,"line":371},20,[158,373,374],{"class":168},"frame.setLinkedMap(main_map)\n",[158,376,378],{"class":160,"line":377},21,[158,379,380],{"class":168},"frame.setFrameSymbol(QgsFillSymbol.createSimple(\n",[158,382,384,387,390,393,396,398,401,403,406,408,411,413,416],{"class":160,"line":383},22,[158,385,386],{"class":168},"    {",[158,388,389],{"class":203},"\"color\"",[158,391,392],{"class":168},": ",[158,394,395],{"class":203},"\"255,0,0,0\"",[158,397,285],{"class":168},[158,399,400],{"class":203},"\"outline_color\"",[158,402,392],{"class":168},[158,404,405],{"class":203},"\"#b91c1c\"",[158,407,285],{"class":168},[158,409,410],{"class":203},"\"outline_width\"",[158,412,392],{"class":168},[158,414,415],{"class":203},"\"0.6\"",[158,417,418],{"class":168},"}))\n",[158,420,422],{"class":160,"line":421},23,[158,423,424],{"class":168},"overview.overviews().addOverview(frame)\n",[14,426,427,431],{},[428,429,430],"strong",{},"Breakdown:"," The overview shows only the coverage layer at the full extent of all districts, and is not atlas-driven, so it stays put while the main map moves. The overview frame is linked to the main map; QGIS draws the main map's current extent as a rectangle on the overview, updating it on every page. A transparent fill with a red outline is the conventional style; a semi-transparent fill can instead dim everything outside the frame by enabling the overview's \"invert\" option. Keeping the overview to one simple layer makes it readable at its small size.",[121,433,435],{"id":434},"highlight-the-current-feature-dim-the-rest","Highlight the current feature, dim the rest",[14,437,438],{},"On the main map, neighbouring districts are useful context but should not compete with the current one. A rule-based renderer compares each feature with the atlas feature.",[14,440,441],{},[29,442,445,448,451,453,456,464,469,475,480,484,487,493,497,501],{"viewBox":443,"role":32,"ariaLabel":444,"xmlns":34},"0 0 760 222","A rule-based style with one rule for the current atlas feature drawn boldly and an else rule drawing other features in pale grey",[36,446,447],{},"Two rules keyed on the atlas feature",[40,449,450],{},"Rule one, for the current feature, uses the expression $id equals @atlas_featureid and draws a bold coloured outline with a light fill. Rule two, the else rule, draws every other feature in pale grey with a thin outline. On each atlas page the variable changes, so the same two rules highlight a different feature.",[44,452],{"x":46,"y":46,"width":47,"height":282,"fill":49},[51,454,455],{"x":53,"y":54,"style":55,"fill":56,"textAnchor":57},"One rule for this page, one for the rest",[44,457],{"x":458,"y":459,"width":460,"height":461,"rx":462,"fill":80,"stroke":81,"style":463},"24","56","340","150","8","stroke-width:2",[51,465,468],{"x":466,"y":467,"style":90,"fill":81,"textAnchor":57},"194","92.6","current feature",[51,470,474],{"x":466,"y":471,"style":472,"fill":473,"textAnchor":57},"120.6","text-anchor:middle;font-size:9.5px;font-family:monospace","#2f3b35","$id = @atlas_featureid",[51,476,479],{"x":466,"y":477,"style":478,"fill":473,"textAnchor":57},"148.6","text-anchor:middle;font-size:10.0px;font-family:sans-serif","bold outline",[51,481,483],{"x":466,"y":482,"style":478,"fill":67,"textAnchor":57},"176.6","light fill",[44,485],{"x":486,"y":459,"width":460,"height":461,"rx":462,"fill":66,"stroke":67,"style":463},"396",[51,488,492],{"x":489,"y":490,"style":491,"fill":56,"textAnchor":57},"566","92.78","text-anchor:middle;font-size:11.5px;font-family:sans-serif;font-weight:bold","ELSE",[51,494,496],{"x":489,"y":495,"style":118,"fill":473,"textAnchor":57},"120.78","all other features",[51,498,500],{"x":489,"y":499,"style":118,"fill":473,"textAnchor":57},"148.78","pale grey",[51,502,504],{"x":489,"y":503,"style":118,"fill":67,"textAnchor":57},"176.78","thin outline",[148,506,508],{"className":150,"code":507,"language":152,"meta":153,"style":153},"from qgis.core import QgsRuleBasedRenderer, QgsSymbol\n\nroot = QgsRuleBasedRenderer.Rule(None)\n\ncurrent_sym = QgsFillSymbol.createSimple(\n    {\"color\": \"238,247,244,255\", \"outline_color\": \"#0f766e\", \"outline_width\": \"0.9\"})\ncurrent = QgsRuleBasedRenderer.Rule(current_sym, filterExp=\"$id = @atlas_featureid\",\n                                    label=\"current district\")\nothers_sym = QgsFillSymbol.createSimple(\n    {\"color\": \"240,235,221,255\", \"outline_color\": \"#b8b1a0\", \"outline_width\": \"0.2\"})\nothers = QgsRuleBasedRenderer.Rule(others_sym, elseRule=True, label=\"other districts\")\n\nroot.appendChild(current)\nroot.appendChild(others)\ncoverage.setRenderer(QgsRuleBasedRenderer(root))\natlas.setHideCoverage(False)\ncoverage.triggerRepaint()\n",[155,509,510,521,525,540,544,554,586,608,620,629,660,689,693,698,703,708,718],{"__ignoreMap":153},[158,511,512,514,516,518],{"class":160,"line":161},[158,513,165],{"class":164},[158,515,169],{"class":168},[158,517,172],{"class":164},[158,519,520],{"class":168}," QgsRuleBasedRenderer, QgsSymbol\n",[158,522,523],{"class":160,"line":178},[158,524,188],{"emptyLinePlaceholder":187},[158,526,527,530,532,535,538],{"class":160,"line":184},[158,528,529],{"class":168},"root ",[158,531,197],{"class":164},[158,533,534],{"class":168}," QgsRuleBasedRenderer.Rule(",[158,536,537],{"class":281},"None",[158,539,207],{"class":168},[158,541,542],{"class":160,"line":191},[158,543,188],{"emptyLinePlaceholder":187},[158,545,546,549,551],{"class":160,"line":210},[158,547,548],{"class":168},"current_sym ",[158,550,197],{"class":164},[158,552,553],{"class":168}," QgsFillSymbol.createSimple(\n",[158,555,556,558,560,562,565,567,569,571,574,576,578,580,583],{"class":160,"line":226},[158,557,386],{"class":168},[158,559,389],{"class":203},[158,561,392],{"class":168},[158,563,564],{"class":203},"\"238,247,244,255\"",[158,566,285],{"class":168},[158,568,400],{"class":203},[158,570,392],{"class":168},[158,572,573],{"class":203},"\"#0f766e\"",[158,575,285],{"class":168},[158,577,410],{"class":203},[158,579,392],{"class":168},[158,581,582],{"class":203},"\"0.9\"",[158,584,585],{"class":168},"})\n",[158,587,588,591,593,596,600,602,605],{"class":160,"line":237},[158,589,590],{"class":168},"current ",[158,592,197],{"class":164},[158,594,595],{"class":168}," QgsRuleBasedRenderer.Rule(current_sym, ",[158,597,599],{"class":598},"s9osk","filterExp",[158,601,197],{"class":164},[158,603,604],{"class":203},"\"$id = @atlas_featureid\"",[158,606,607],{"class":168},",\n",[158,609,610,613,615,618],{"class":160,"line":248},[158,611,612],{"class":598},"                                    label",[158,614,197],{"class":164},[158,616,617],{"class":203},"\"current district\"",[158,619,207],{"class":168},[158,621,622,625,627],{"class":160,"line":253},[158,623,624],{"class":168},"others_sym ",[158,626,197],{"class":164},[158,628,553],{"class":168},[158,630,631,633,635,637,640,642,644,646,649,651,653,655,658],{"class":160,"line":264},[158,632,386],{"class":168},[158,634,389],{"class":203},[158,636,392],{"class":168},[158,638,639],{"class":203},"\"240,235,221,255\"",[158,641,285],{"class":168},[158,643,400],{"class":203},[158,645,392],{"class":168},[158,647,648],{"class":203},"\"#b8b1a0\"",[158,650,285],{"class":168},[158,652,410],{"class":203},[158,654,392],{"class":168},[158,656,657],{"class":203},"\"0.2\"",[158,659,585],{"class":168},[158,661,662,665,667,670,673,675,677,679,682,684,687],{"class":160,"line":275},[158,663,664],{"class":168},"others ",[158,666,197],{"class":164},[158,668,669],{"class":168}," QgsRuleBasedRenderer.Rule(others_sym, ",[158,671,672],{"class":598},"elseRule",[158,674,197],{"class":164},[158,676,322],{"class":281},[158,678,285],{"class":168},[158,680,681],{"class":598},"label",[158,683,197],{"class":164},[158,685,686],{"class":203},"\"other districts\"",[158,688,207],{"class":168},[158,690,691],{"class":160,"line":294},[158,692,188],{"emptyLinePlaceholder":187},[158,694,695],{"class":160,"line":310},[158,696,697],{"class":168},"root.appendChild(current)\n",[158,699,700],{"class":160,"line":316},[158,701,702],{"class":168},"root.appendChild(others)\n",[158,704,705],{"class":160,"line":327},[158,706,707],{"class":168},"coverage.setRenderer(QgsRuleBasedRenderer(root))\n",[158,709,710,713,716],{"class":160,"line":333},[158,711,712],{"class":168},"atlas.setHideCoverage(",[158,714,715],{"class":281},"False",[158,717,207],{"class":168},[158,719,720],{"class":160,"line":343},[158,721,722],{"class":168},"coverage.triggerRepaint()\n",[14,724,725,727,728,731,732,735,736,139],{},[428,726,430],{}," ",[155,729,730],{},"@atlas_featureid"," holds the id of the page's feature during atlas rendering; comparing it with ",[155,733,734],{},"$id"," matches exactly one feature. The else rule catches everything else. Because the variable changes per page, one renderer highlights the right district on every page. Outside atlas rendering — in the normal map canvas — the variable is NULL, so every district draws with the else style, which is a reasonable default. The coverage layer must be visible on the main map for this to work, so hiding coverage is turned off. More on rules in ",[21,737,739],{"href":738},"\u002Fpyqgis-cartography-visualization\u002Fgraduated-categorized-renderers\u002Frule-based-renderer-pyqgis\u002F","rule-based renderers",[121,741,743],{"id":742},"mask-everything-outside-the-current-feature","Mask everything outside the current feature",[14,745,746],{},"A stronger effect fades all data outside the current district — roads, buildings, land use — not just neighbouring boundaries. An inverted polygon renderer drawing a semi-transparent fill everywhere except the current feature does it.",[148,748,750],{"className":150,"code":749,"language":152,"meta":153,"style":153},"from qgis.core import QgsInvertedPolygonRenderer, QgsVectorLayer\n\nmask_layer = QgsVectorLayer(coverage.source(), \"atlas mask\", coverage.providerType())\nmask_root = QgsRuleBasedRenderer.Rule(None)\nmask_rule = QgsRuleBasedRenderer.Rule(\n    QgsFillSymbol.createSimple({\"color\": \"255,255,255,190\", \"outline_style\": \"no\"}),\n    filterExp=\"$id = @atlas_featureid\")\nmask_root.appendChild(mask_rule)\nmask_layer.setRenderer(QgsInvertedPolygonRenderer(QgsRuleBasedRenderer(mask_root)))\nQgsProject.instance().addMapLayer(mask_layer, False)\nQgsProject.instance().layerTreeRoot().insertLayer(0, mask_layer)\nmain_map.setLayers([mask_layer] + [l for l in main_map.layers() if l.id() != mask_layer.id()])\n",[155,751,752,763,767,783,796,806,831,842,847,852,861,871],{"__ignoreMap":153},[158,753,754,756,758,760],{"class":160,"line":161},[158,755,165],{"class":164},[158,757,169],{"class":168},[158,759,172],{"class":164},[158,761,762],{"class":168}," QgsInvertedPolygonRenderer, QgsVectorLayer\n",[158,764,765],{"class":160,"line":178},[158,766,188],{"emptyLinePlaceholder":187},[158,768,769,772,774,777,780],{"class":160,"line":184},[158,770,771],{"class":168},"mask_layer ",[158,773,197],{"class":164},[158,775,776],{"class":168}," QgsVectorLayer(coverage.source(), ",[158,778,779],{"class":203},"\"atlas mask\"",[158,781,782],{"class":168},", coverage.providerType())\n",[158,784,785,788,790,792,794],{"class":160,"line":191},[158,786,787],{"class":168},"mask_root ",[158,789,197],{"class":164},[158,791,534],{"class":168},[158,793,537],{"class":281},[158,795,207],{"class":168},[158,797,798,801,803],{"class":160,"line":210},[158,799,800],{"class":168},"mask_rule ",[158,802,197],{"class":164},[158,804,805],{"class":168}," QgsRuleBasedRenderer.Rule(\n",[158,807,808,811,813,815,818,820,823,825,828],{"class":160,"line":226},[158,809,810],{"class":168},"    QgsFillSymbol.createSimple({",[158,812,389],{"class":203},[158,814,392],{"class":168},[158,816,817],{"class":203},"\"255,255,255,190\"",[158,819,285],{"class":168},[158,821,822],{"class":203},"\"outline_style\"",[158,824,392],{"class":168},[158,826,827],{"class":203},"\"no\"",[158,829,830],{"class":168},"}),\n",[158,832,833,836,838,840],{"class":160,"line":237},[158,834,835],{"class":598},"    filterExp",[158,837,197],{"class":164},[158,839,604],{"class":203},[158,841,207],{"class":168},[158,843,844],{"class":160,"line":248},[158,845,846],{"class":168},"mask_root.appendChild(mask_rule)\n",[158,848,849],{"class":160,"line":253},[158,850,851],{"class":168},"mask_layer.setRenderer(QgsInvertedPolygonRenderer(QgsRuleBasedRenderer(mask_root)))\n",[158,853,854,857,859],{"class":160,"line":264},[158,855,856],{"class":168},"QgsProject.instance().addMapLayer(mask_layer, ",[158,858,715],{"class":281},[158,860,207],{"class":168},[158,862,863,866,868],{"class":160,"line":275},[158,864,865],{"class":168},"QgsProject.instance().layerTreeRoot().insertLayer(",[158,867,46],{"class":281},[158,869,870],{"class":168},", mask_layer)\n",[158,872,873,876,879,882,885,888,891,894,897,900,903],{"class":160,"line":294},[158,874,875],{"class":168},"main_map.setLayers([mask_layer] ",[158,877,878],{"class":164},"+",[158,880,881],{"class":168}," [l ",[158,883,884],{"class":164},"for",[158,886,887],{"class":168}," l ",[158,889,890],{"class":164},"in",[158,892,893],{"class":168}," main_map.layers() ",[158,895,896],{"class":164},"if",[158,898,899],{"class":168}," l.id() ",[158,901,902],{"class":164},"!=",[158,904,905],{"class":168}," mask_layer.id()])\n",[14,907,908,910,911,915],{},[428,909,430],{}," An inverted polygon renderer fills the area ",[912,913,914],"em",{},"outside"," the polygons its inner renderer draws; restricting the inner rule to the atlas feature means the white wash covers everything except the current district. A second copy of the coverage layer carries the mask so the boundary styling on the original stays independent. Putting the mask first in the map's layer list draws it on top of the data. The alpha value (190 of 255) controls how strongly the surroundings fade; context should stay faintly visible, not disappear.",[121,917,919],{"id":918},"label-only-the-current-feature","Label only the current feature",[14,921,922],{},"District names on every neighbouring polygon clutter the page. A labelling rule restricted to the atlas feature shows only the current name, while neighbours stay unlabelled or get smaller labels.",[148,924,926],{"className":150,"code":925,"language":152,"meta":153,"style":153},"from qgis.core import (QgsPalLayerSettings, QgsRuleBasedLabeling, QgsTextFormat)\nfrom qgis.PyQt.QtGui import QFont\n\ndef label_settings(size, bold):\n    s = QgsPalLayerSettings()\n    s.fieldName = \"name\"\n    fmt = QgsTextFormat()\n    f = QFont(\"Noto Sans\", size)\n    f.setBold(bold)\n    fmt.setFont(f)\n    fmt.setSize(size)\n    s.setFormat(fmt)\n    return s\n\nlab_root = QgsRuleBasedLabeling.Rule(None)\nlab_root.appendChild(QgsRuleBasedLabeling.Rule(label_settings(14, True),\n                     filterExpression=\"$id = @atlas_featureid\"))\nlab_root.appendChild(QgsRuleBasedLabeling.Rule(label_settings(7, False),\n                     filterExpression=\"$id \u003C> @atlas_featureid\"))\ncoverage.setLabeling(QgsRuleBasedLabeling(lab_root))\ncoverage.setLabelsEnabled(True)\n",[155,927,928,939,951,955,967,977,987,997,1013,1018,1023,1028,1033,1041,1045,1059,1074,1086,1099,1110,1115],{"__ignoreMap":153},[158,929,930,932,934,936],{"class":160,"line":161},[158,931,165],{"class":164},[158,933,169],{"class":168},[158,935,172],{"class":164},[158,937,938],{"class":168}," (QgsPalLayerSettings, QgsRuleBasedLabeling, QgsTextFormat)\n",[158,940,941,943,946,948],{"class":160,"line":178},[158,942,165],{"class":164},[158,944,945],{"class":168}," qgis.PyQt.QtGui ",[158,947,172],{"class":164},[158,949,950],{"class":168}," QFont\n",[158,952,953],{"class":160,"line":184},[158,954,188],{"emptyLinePlaceholder":187},[158,956,957,960,964],{"class":160,"line":191},[158,958,959],{"class":164},"def",[158,961,963],{"class":962},"svObZ"," label_settings",[158,965,966],{"class":168},"(size, bold):\n",[158,968,969,972,974],{"class":160,"line":210},[158,970,971],{"class":168},"    s ",[158,973,197],{"class":164},[158,975,976],{"class":168}," QgsPalLayerSettings()\n",[158,978,979,982,984],{"class":160,"line":226},[158,980,981],{"class":168},"    s.fieldName ",[158,983,197],{"class":164},[158,985,986],{"class":203}," \"name\"\n",[158,988,989,992,994],{"class":160,"line":237},[158,990,991],{"class":168},"    fmt ",[158,993,197],{"class":164},[158,995,996],{"class":168}," QgsTextFormat()\n",[158,998,999,1002,1004,1007,1010],{"class":160,"line":248},[158,1000,1001],{"class":168},"    f ",[158,1003,197],{"class":164},[158,1005,1006],{"class":168}," QFont(",[158,1008,1009],{"class":203},"\"Noto Sans\"",[158,1011,1012],{"class":168},", size)\n",[158,1014,1015],{"class":160,"line":253},[158,1016,1017],{"class":168},"    f.setBold(bold)\n",[158,1019,1020],{"class":160,"line":264},[158,1021,1022],{"class":168},"    fmt.setFont(f)\n",[158,1024,1025],{"class":160,"line":275},[158,1026,1027],{"class":168},"    fmt.setSize(size)\n",[158,1029,1030],{"class":160,"line":294},[158,1031,1032],{"class":168},"    s.setFormat(fmt)\n",[158,1034,1035,1038],{"class":160,"line":310},[158,1036,1037],{"class":164},"    return",[158,1039,1040],{"class":168}," s\n",[158,1042,1043],{"class":160,"line":316},[158,1044,188],{"emptyLinePlaceholder":187},[158,1046,1047,1050,1052,1055,1057],{"class":160,"line":327},[158,1048,1049],{"class":168},"lab_root ",[158,1051,197],{"class":164},[158,1053,1054],{"class":168}," QgsRuleBasedLabeling.Rule(",[158,1056,537],{"class":281},[158,1058,207],{"class":168},[158,1060,1061,1064,1067,1069,1071],{"class":160,"line":333},[158,1062,1063],{"class":168},"lab_root.appendChild(QgsRuleBasedLabeling.Rule(label_settings(",[158,1065,1066],{"class":281},"14",[158,1068,285],{"class":168},[158,1070,322],{"class":281},[158,1072,1073],{"class":168},"),\n",[158,1075,1076,1079,1081,1083],{"class":160,"line":343},[158,1077,1078],{"class":598},"                     filterExpression",[158,1080,197],{"class":164},[158,1082,604],{"class":203},[158,1084,1085],{"class":168},"))\n",[158,1087,1088,1090,1093,1095,1097],{"class":160,"line":349},[158,1089,1063],{"class":168},[158,1091,1092],{"class":281},"7",[158,1094,285],{"class":168},[158,1096,715],{"class":281},[158,1098,1073],{"class":168},[158,1100,1101,1103,1105,1108],{"class":160,"line":354},[158,1102,1078],{"class":598},[158,1104,197],{"class":164},[158,1106,1107],{"class":203},"\"$id \u003C> @atlas_featureid\"",[158,1109,1085],{"class":168},[158,1111,1112],{"class":160,"line":371},[158,1113,1114],{"class":168},"coverage.setLabeling(QgsRuleBasedLabeling(lab_root))\n",[158,1116,1117,1120,1122],{"class":160,"line":377},[158,1118,1119],{"class":168},"coverage.setLabelsEnabled(",[158,1121,322],{"class":281},[158,1123,207],{"class":168},[14,1125,1126,1128,1129,1132,1133,1137],{},[428,1127,430],{}," Two labelling rules mirror the two style rules: a large bold label for the current district and a small label for neighbours, which gives orientation without competing. Dropping the second rule leaves neighbours unlabelled entirely. The same pattern works for any layer — label only the schools inside the current district with ",[155,1130,1131],{},"within($geometry, @atlas_geometry)",". See ",[21,1134,1136],{"href":1135},"\u002Fpyqgis-cartography-visualization\u002Flabeling-and-annotations\u002Fadd-rule-based-labels-pyqgis\u002F","rule-based labels"," for the labelling side in detail.",[121,1139,1141],{"id":1140},"show-items-only-on-some-pages","Show items only on some pages",[14,1143,1144],{},"Some context is only needed sometimes: an inset for very small districts, a \"continued on next page\" note for districts split across sheets, an extra legend entry where a rare land use appears. Layout items can be shown or hidden per page with a data-defined exclusion expression evaluated against the atlas feature.",[148,1146,1148],{"className":150,"code":1147,"language":152,"meta":153,"style":153},"from qgis.core import QgsLayoutObject, QgsProperty\n\ninset = QgsLayoutItemMap(layout)\ninset.setId(\"detail_inset\")\ninset.attemptMove(QgsLayoutPoint(222, 66, QgsUnitTypes.LayoutMillimeters))\ninset.attemptResize(QgsLayoutSize(62, 48, QgsUnitTypes.LayoutMillimeters))\ninset.setAtlasDriven(True)\ninset.setAtlasScalingMode(QgsLayoutItemMap.Auto)\ninset.setAtlasMargin(0.4)\nlayout.addLayoutItem(inset)\n\ninset.dataDefinedProperties().setProperty(\n    QgsLayoutObject.ExcludeFromExports,\n    QgsProperty.fromExpression(\"area(@atlas_geometry) > 2000000\"))\n",[155,1149,1150,1161,1165,1174,1184,1198,1211,1220,1225,1235,1240,1244,1249,1254],{"__ignoreMap":153},[158,1151,1152,1154,1156,1158],{"class":160,"line":161},[158,1153,165],{"class":164},[158,1155,169],{"class":168},[158,1157,172],{"class":164},[158,1159,1160],{"class":168}," QgsLayoutObject, QgsProperty\n",[158,1162,1163],{"class":160,"line":178},[158,1164,188],{"emptyLinePlaceholder":187},[158,1166,1167,1170,1172],{"class":160,"line":184},[158,1168,1169],{"class":168},"inset ",[158,1171,197],{"class":164},[158,1173,261],{"class":168},[158,1175,1176,1179,1182],{"class":160,"line":191},[158,1177,1178],{"class":168},"inset.setId(",[158,1180,1181],{"class":203},"\"detail_inset\"",[158,1183,207],{"class":168},[158,1185,1186,1189,1191,1193,1196],{"class":160,"line":210},[158,1187,1188],{"class":168},"inset.attemptMove(QgsLayoutPoint(",[158,1190,282],{"class":281},[158,1192,285],{"class":168},[158,1194,1195],{"class":281},"66",[158,1197,291],{"class":168},[158,1199,1200,1203,1205,1207,1209],{"class":160,"line":226},[158,1201,1202],{"class":168},"inset.attemptResize(QgsLayoutSize(",[158,1204,300],{"class":281},[158,1206,285],{"class":168},[158,1208,305],{"class":281},[158,1210,291],{"class":168},[158,1212,1213,1216,1218],{"class":160,"line":237},[158,1214,1215],{"class":168},"inset.setAtlasDriven(",[158,1217,322],{"class":281},[158,1219,207],{"class":168},[158,1221,1222],{"class":160,"line":248},[158,1223,1224],{"class":168},"inset.setAtlasScalingMode(QgsLayoutItemMap.Auto)\n",[158,1226,1227,1230,1233],{"class":160,"line":253},[158,1228,1229],{"class":168},"inset.setAtlasMargin(",[158,1231,1232],{"class":281},"0.4",[158,1234,207],{"class":168},[158,1236,1237],{"class":160,"line":264},[158,1238,1239],{"class":168},"layout.addLayoutItem(inset)\n",[158,1241,1242],{"class":160,"line":275},[158,1243,188],{"emptyLinePlaceholder":187},[158,1245,1246],{"class":160,"line":294},[158,1247,1248],{"class":168},"inset.dataDefinedProperties().setProperty(\n",[158,1250,1251],{"class":160,"line":310},[158,1252,1253],{"class":168},"    QgsLayoutObject.ExcludeFromExports,\n",[158,1255,1256,1259,1262],{"class":160,"line":316},[158,1257,1258],{"class":168},"    QgsProperty.fromExpression(",[158,1260,1261],{"class":203},"\"area(@atlas_geometry) > 2000000\"",[158,1263,1085],{"class":168},[14,1265,1266,1268,1269,1272,1273,1276],{},[428,1267,430],{}," The inset is atlas-driven with a generous margin, showing the current district with more surrounding context. The data-defined \"exclude from exports\" property hides it on pages where the district is larger than two square kilometres, so the inset appears only for small districts that the main map renders at a scale where context is lost. Any expression over ",[155,1270,1271],{},"@atlas_feature"," or ",[155,1274,1275],{},"@atlas_geometry"," works, which makes page-specific layout elements possible without separate layouts. Remember that the main and overview maps are unaffected; only the item carrying the property toggles.",[121,1278,1280],{"id":1279},"check-the-result-in-exports","Check the result in exports",[14,1282,1283],{},"Atlas variables only have values during atlas rendering, so the canvas cannot show the final look. Export a few pages as images to check highlighting, masking and labels.",[14,1285,1286],{},[29,1287,1290,1293,1296,1299,1313,1316,1320,1325,1329,1333,1338,1342,1347,1351,1355,1361,1366],{"viewBox":1288,"role":32,"ariaLabel":1289,"xmlns":34},"0 0 760 196","Checking atlas highlighting by exporting a few sample pages rather than looking at the map canvas, where atlas variables are empty",[36,1291,1292],{},"Check a few pages, not the canvas",[40,1294,1295],{},"In the map canvas the atlas variables are empty, so highlight rules do not fire and every feature looks the same. Previewing the atlas in the layout designer or exporting the first, a middle and the last page as small PNGs shows the real result, including features at the edge of the region where the overview frame and mask behave differently.",[44,1297],{"x":46,"y":46,"width":47,"height":1298,"fill":49},"196",[1300,1301,1302],"defs",{},[1303,1304,1309],"marker",{"id":1305,"viewBox":1306,"refX":462,"refY":1307,"markerWidth":1092,"markerHeight":1092,"orient":1308},"hlCheckArrow","0 0 10 10","5","auto-start-reverse",[1310,1311],"path",{"d":1312,"fill":473},"M0 0 L10 5 L0 10 z",[51,1314,1315],{"x":53,"y":54,"style":55,"fill":56,"textAnchor":57},"Variables exist only while the atlas renders",[44,1317],{"x":458,"y":108,"width":282,"height":1318,"rx":462,"fill":1319,"stroke":112,"style":463},"120","#fdf2e2",[51,1321,1324],{"x":1322,"y":1323,"style":491,"fill":112,"textAnchor":57},"135","97.78","map canvas",[51,1326,1328],{"x":1322,"y":1327,"style":118,"fill":67,"textAnchor":57},"123.78","atlas_featureid NULL",[51,1330,1332],{"x":1322,"y":1331,"style":118,"fill":67,"textAnchor":57},"149.78","no highlight",[160,1334],{"x1":1335,"y1":1318,"x2":1336,"y2":1318,"stroke":473,"style":1337},"246","288","stroke-width:1.8;marker-end:url(#hlCheckArrow)",[44,1339],{"x":1340,"y":108,"width":95,"height":1318,"rx":462,"fill":1319,"stroke":1341,"style":463},"292","#b45309",[51,1343,1346],{"x":1344,"y":1345,"style":491,"fill":1341,"textAnchor":57},"392","110.78","export samples",[51,1348,1350],{"x":1344,"y":1349,"style":118,"fill":67,"textAnchor":57},"136.78","first · middle · last",[160,1352],{"x1":1353,"y1":1318,"x2":1354,"y2":1318,"stroke":473,"style":1337},"492","534",[44,1356],{"x":1357,"y":108,"width":1358,"height":1318,"rx":462,"fill":1359,"stroke":1360,"style":463},"538","198","#e8efe6","#15803d",[51,1362,1365],{"x":1363,"y":1345,"style":491,"fill":1364,"textAnchor":57},"637","#166534","check",[51,1367,1368],{"x":1363,"y":1349,"style":118,"fill":67,"textAnchor":57},"frame, mask, labels",[148,1370,1372],{"className":150,"code":1371,"language":152,"meta":153,"style":153},"from qgis.core import QgsLayoutExporter\n\natlas.beginRender()\nfor i in (0, atlas.count() \u002F\u002F 2, atlas.count() - 1):\n    atlas.seekTo(i)\n    QgsLayoutExporter(layout).exportToImage(\n        f\"\u002Fdata\u002Fmaps\u002Fpreview_{i:03d}.png\", QgsLayoutExporter.ImageExportSettings())\natlas.endRender()\nprint(\"previews written\")\n",[155,1373,1374,1385,1389,1394,1428,1433,1438,1464,1469],{"__ignoreMap":153},[158,1375,1376,1378,1380,1382],{"class":160,"line":161},[158,1377,165],{"class":164},[158,1379,169],{"class":168},[158,1381,172],{"class":164},[158,1383,1384],{"class":168}," QgsLayoutExporter\n",[158,1386,1387],{"class":160,"line":178},[158,1388,188],{"emptyLinePlaceholder":187},[158,1390,1391],{"class":160,"line":184},[158,1392,1393],{"class":168},"atlas.beginRender()\n",[158,1395,1396,1398,1401,1403,1406,1408,1411,1414,1417,1419,1422,1425],{"class":160,"line":191},[158,1397,884],{"class":164},[158,1399,1400],{"class":168}," i ",[158,1402,890],{"class":164},[158,1404,1405],{"class":168}," (",[158,1407,46],{"class":281},[158,1409,1410],{"class":168},", atlas.count() ",[158,1412,1413],{"class":164},"\u002F\u002F",[158,1415,1416],{"class":281}," 2",[158,1418,1410],{"class":168},[158,1420,1421],{"class":164},"-",[158,1423,1424],{"class":281}," 1",[158,1426,1427],{"class":168},"):\n",[158,1429,1430],{"class":160,"line":210},[158,1431,1432],{"class":168},"    atlas.seekTo(i)\n",[158,1434,1435],{"class":160,"line":226},[158,1436,1437],{"class":168},"    QgsLayoutExporter(layout).exportToImage(\n",[158,1439,1440,1443,1446,1449,1452,1455,1458,1461],{"class":160,"line":237},[158,1441,1442],{"class":164},"        f",[158,1444,1445],{"class":203},"\"\u002Fdata\u002Fmaps\u002Fpreview_",[158,1447,1448],{"class":281},"{",[158,1450,1451],{"class":168},"i",[158,1453,1454],{"class":164},":03d",[158,1456,1457],{"class":281},"}",[158,1459,1460],{"class":203},".png\"",[158,1462,1463],{"class":168},", QgsLayoutExporter.ImageExportSettings())\n",[158,1465,1466],{"class":160,"line":248},[158,1467,1468],{"class":168},"atlas.endRender()\n",[158,1470,1471,1474,1477,1480],{"class":160,"line":253},[158,1472,1473],{"class":281},"print",[158,1475,1476],{"class":168},"(",[158,1478,1479],{"class":203},"\"previews written\"",[158,1481,207],{"class":168},[14,1483,1484,727,1486,1489,1490,1493],{},[428,1485,430],{},[155,1487,1488],{},"beginRender"," and ",[155,1491,1492],{},"seekTo"," put the layout into atlas mode for a specific page, so expressions using atlas variables evaluate as they will in the final export. Previewing the first, middle and last page catches most problems, including edge districts where the overview frame touches the overview map's border. Low-resolution PNGs are quick to write and view.",[121,1495,1497],{"id":1496},"qgis-version-compatibility","QGIS version compatibility",[14,1499,1500,1501,1504,1505,285,1507,1489,1509,1511],{},"Overview maps, atlas variables, rule-based renderers and labelling, and the inverted polygon renderer work on QGIS 3.34 LTR, 3.40 LTR and QGIS 4. On QGIS 4, unit enums use ",[155,1502,1503],{},"Qgis.LayoutUnit.Millimeters","; the variable names ",[155,1506,730],{},[155,1508,1271],{},[155,1510,1275],{}," are unchanged.",[121,1513,1515],{"id":1514},"troubleshooting","Troubleshooting",[126,1517,1518,1528,1534,1545],{},[129,1519,1520,1523,1524,1527],{},[428,1521,1522],{},"No highlight in exports."," The coverage layer is hidden by the atlas; turn ",[155,1525,1526],{},"setHideCoverage"," off when it carries the highlight style.",[129,1529,1530,1533],{},[428,1531,1532],{},"The overview frame is missing."," The frame is not linked to the main map, or the overview is atlas-driven too.",[129,1535,1536,1539,1540,1542,1543,139],{},[428,1537,1538],{},"Everything is masked."," The mask rule's expression does not match; check ",[155,1541,734],{}," against ",[155,1544,730],{},[129,1546,1547,1550,1551,139],{},[428,1548,1549],{},"Highlight works in the designer but not from Python."," Exports were made without ",[155,1552,1488],{},[121,1554,1556],{"id":1555},"conclusion","Conclusion",[14,1558,1559,1560,1562],{},"Add a fixed overview map with a frame linked to the main map, highlight the current feature with a rule on ",[155,1561,474],{}," and dim the rest with an else rule, mask the surroundings with an inverted polygon renderer on a copy of the coverage layer, label only the current feature prominently, and check sample pages from an atlas render rather than the canvas.",[121,1564,1566],{"id":1565},"frequently-asked-questions","Frequently Asked Questions",[14,1568,1569,1572],{},[428,1570,1571],{},"Can the overview be another layer, such as a basemap?","\nYes — any layers; keep it simple enough to read at small size.",[14,1574,1575,1578,1579,1581,1582,139],{},[428,1576,1577],{},"Can I highlight on a different layer than the coverage?","\nYes: compare with ",[155,1580,1275],{},", for example ",[155,1583,1584],{},"intersects($geometry, @atlas_geometry)",[14,1586,1587,1590],{},[428,1588,1589],{},"Does this work with QGIS Server atlas requests?","\nYes, atlas variables are available wherever atlases render.",[14,1592,1593,1596],{},[428,1594,1595],{},"Can the overview zoom to the region around each page instead of the whole area?","\nMake the overview atlas-driven with a large margin, or a fixed scale several times smaller than the main map; it then follows each page while still showing wider context.",[14,1598,1599,1602],{},[428,1600,1601],{},"How do I fade instead of mask completely?","\nLower the mask fill's alpha so surroundings stay visible.",[121,1604,1606],{"id":1605},"related","Related",[126,1608,1609,1614,1620,1626,1631],{},[129,1610,1611,1613],{},[21,1612,24],{"href":23}," — the guide this recipe belongs to",[129,1615,1616],{},[21,1617,1619],{"href":1618},"\u002Fspatial-data-processing-automation\u002Fautomating-atlas-map-series\u002Ffilter-and-sort-atlas-features-pyqgis\u002F","Filter and Sort Atlas Features in PyQGIS",[129,1621,1622],{},[21,1623,1625],{"href":1624},"\u002Fspatial-data-processing-automation\u002Fautomating-atlas-map-series\u002Fatlas-expressions-and-dynamic-text-pyqgis\u002F","Atlas Expressions and Dynamic Text in PyQGIS",[129,1627,1628],{},[21,1629,1630],{"href":738},"Create a Rule-Based Renderer in PyQGIS",[129,1632,1633],{},[21,1634,1636],{"href":1635},"\u002Fspatial-data-processing-automation\u002Fautomated-map-layout-generation\u002Fadd-map-item-and-set-extent-pyqgis\u002F","Add a Map Item and Set Its Extent in PyQGIS",[1638,1639,1640],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":153,"searchDepth":178,"depth":178,"links":1642},[1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654],{"id":123,"depth":178,"text":124},{"id":142,"depth":178,"text":143},{"id":434,"depth":178,"text":435},{"id":742,"depth":178,"text":743},{"id":918,"depth":178,"text":919},{"id":1140,"depth":178,"text":1141},{"id":1279,"depth":178,"text":1280},{"id":1496,"depth":178,"text":1497},{"id":1514,"depth":178,"text":1515},{"id":1555,"depth":178,"text":1556},{"id":1565,"depth":178,"text":1566},{"id":1605,"depth":178,"text":1606},"Make each atlas page show where it is — overview maps with an extent frame, rule-based styles that highlight the current atlas feature and dim the rest, masking everything outside it, labels that switch on only for the current feature, and keeping all of it working in exports.","md",{"slug":1658,"type":1659,"breadcrumb":1660,"datePublished":1661,"dateModified":1661},"highlight-atlas-feature-in-overview-map-pyqgis","article","Highlight the Atlas Feature","2026-10-02","\u002Fspatial-data-processing-automation\u002Fautomating-atlas-map-series\u002Fhighlight-atlas-feature-in-overview-map-pyqgis",{"title":5,"description":1655},"spatial-data-processing-automation\u002Fautomating-atlas-map-series\u002Fhighlight-atlas-feature-in-overview-map-pyqgis\u002Findex","qZ_Dooeb-0Ar-s3bXb56Pfqv4sJZKBUFIHZBo_ff5Qk",1790966260662]