Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE]色覚特性対応のための色の切り替え機能 #48

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions scatter/next-app/components/DesktopFullscreenFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {XIcon} from 'lucide-react'
import { XIcon } from 'lucide-react'
import React from 'react'
import {Translator} from '@/hooks/useTranslatorAndReplacements'
import {Argument, PropertyMap} from '@/types'
import { PaletteType } from '@/hooks/useColorPalettes'
import { Translator } from '@/hooks/useTranslatorAndReplacements'
import { Argument, PropertyMap } from '@/types'

type Props = {
translator: Translator
Expand All @@ -21,10 +22,12 @@ type Props = {
filtered: number
filter: (arg: Argument) => boolean
}
paletteType: PaletteType
setPaletteType: (type: PaletteType) => void
}

export function DesktopFullscreenFilter(props: Props) {
const {t} = props.translator
const { t } = props.translator
return (
<div
className="absolute top-0 left-0 w-[400px] p-4 bg-gray-100 overflow-y-auto z-10 h-full shadow-md"
Expand All @@ -35,7 +38,7 @@ export function DesktopFullscreenFilter(props: Props) {
{t('toolsFilterSettings')}
</h2>
<button onClick={props.onClose}>
<XIcon/>
<XIcon />
</button>
</div>
{/* Search */}
Expand Down Expand Up @@ -78,6 +81,20 @@ export function DesktopFullscreenFilter(props: Props) {
})}
</dl>

カラーパレット
<select
className="w-[120px] m-1 px-2 py-1 rounded-lg bg-white text-gray-700 text-sm border border-gray-300 hover:border-gray-400"
value={props.paletteType}
onChange={(e) => props.setPaletteType(e.target.value as PaletteType)}
>
<option value="default">デフォルト</option>
<option value="colorUniversal">カラーユニバーサル</option>
<option value="proto">第一色覚</option>
<option value="deutero">第二色覚</option>
<option value="trito">第三色覚</option>
</select>


{/* Votes */}
{props.dataHasVotes && (
<div>
Expand Down
20 changes: 10 additions & 10 deletions scatter/next-app/components/DesktopFullscreenTools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
TagIcon
} from 'lucide-react'
import React from 'react'
import {Translator} from '@/hooks/useTranslatorAndReplacements'
import { Translator } from '@/hooks/useTranslatorAndReplacements'

type Props = {
canFilter: boolean // !!propertyMap
Expand All @@ -28,42 +28,42 @@ type Props = {
}

export function DesktopFullscreenTools(props: Props) {
const {t} = props.translator
const { t } = props.translator
return (
<div className="absolute top-0 w-full p-2" style={{backgroundColor: 'rgba(255, 255, 255, 0.5)'}}>
<div className="absolute top-0 w-full p-2" style={{ backgroundColor: 'rgba(255, 255, 255, 0.5)' }}>
<div className={'flex justify-between items-center'}>
<div className={'flex'}>
{props.canFilter && (
<button className="w-[80px] m-1 flex flex-col items-center" onClick={() => props.setShowSettings(x => !x)}>
<SlidersHorizontalIcon className={props.showSettings ? 'text-blue-500' : 'text-gray-500'}/>
<SlidersHorizontalIcon className={props.showSettings ? 'text-blue-500' : 'text-gray-500'} />
<p className={'text-xs text-gray-700'}>{t('toolsFilterSettings')}</p>
</button>
)}
<button className="w-[80px] m-1 flex flex-col items-center" onClick={() => props.setShowLabels(x => !x)}>
<TagIcon className={props.showLabels ? 'text-blue-500' : 'text-gray-500'}/>
<TagIcon className={props.showLabels ? 'text-blue-500' : 'text-gray-500'} />
<p className={'text-xs text-gray-700'}>{t('toolsDisplayLabels')}</p>
</button>
<button className="w-[80px] m-1 flex flex-col items-center" onClick={() => props.setShowTitle(x => !x)}>
<AtSignIcon className={props.showTitle ? 'text-blue-500' : 'text-gray-500'}/>
<AtSignIcon className={props.showTitle ? 'text-blue-500' : 'text-gray-500'} />
<p className={'text-xs text-gray-700'}>{t('toolsDisplayTitle')}</p>
</button>
<button className="w-[80px] m-1 flex flex-col items-center" onClick={() => props.setShowRatio(x => !x)}>
<ChartPieIcon className={props.showRatio ? 'text-blue-500' : 'text-gray-500'}/>
<ChartPieIcon className={props.showRatio ? 'text-blue-500' : 'text-gray-500'} />
<p className={'text-xs text-gray-700'}>{t('toolsDisplayPercentage')}</p>
</button>
<button className="w-[80px] m-1 flex flex-col items-center"
onClick={() => typeof props.zoomReset === 'function' && props.zoomReset()}>
<ScanSearchIcon className={props.zoomReset ? 'text-blue-500' : 'text-gray-500'}/>
<ScanSearchIcon className={props.zoomReset ? 'text-blue-500' : 'text-gray-500'} />
<p className={'text-xs text-gray-700'}>{t('toolsResetPosition')}</p>
</button>
</div>
<div className={'flex justify-between items-center'}>
<button className="w-[80px] m-1 flex flex-col items-center" onClick={() => props.setShowFavorites(x => !x)}>
<BookMarkedIcon className={'text-gray-700'}/>
<BookMarkedIcon className={'text-gray-700'} />
<p className={'text-xs text-gray-700'}>{t('toolsDisplayFavorites')}</p>
</button>
<button className="w-[80px] m-1 flex flex-col items-center" onClick={props.exitFullScreen}>
<Minimize2Icon className={'text-gray-700'}/>
<Minimize2Icon className={'text-gray-700'} />
<p className={'text-xs text-gray-700'}>{t('toolsExitFullScreen')}</p>
</button>
</div>
Expand Down
72 changes: 41 additions & 31 deletions scatter/next-app/components/DesktopMap.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import {useGesture} from '@use-gesture/react'
import React, {useEffect, useRef, useState} from 'react'
import { useGesture } from '@use-gesture/react'
import React, { useEffect, useRef, useState } from 'react'
import CustomTitle from '@/components/CustomTitle'
import {DesktopFullscreenFavorites} from '@/components/DesktopFullscreenFavorites'
import {DesktopFullscreenFilter} from '@/components/DesktopFullscreenFilter'
import {DesktopFullscreenTools} from '@/components/DesktopFullscreenTools'
import { DesktopFullscreenFavorites } from '@/components/DesktopFullscreenFavorites'
import { DesktopFullscreenFilter } from '@/components/DesktopFullscreenFilter'
import { DesktopFullscreenTools } from '@/components/DesktopFullscreenTools'
import Tooltip from '@/components/DesktopTooltip'
import useAutoResize from '@/hooks/useAutoResize'
import {ColorFunc} from '@/hooks/useClusterColor'
import { ColorFunc } from '@/hooks/useClusterColor'
import { PaletteType } from '@/hooks/useColorPalettes'
import useFilter from '@/hooks/useFilter'
import useInferredFeatures from '@/hooks/useInferredFeatures'
import useRelativePositions from '@/hooks/useRelativePositions'
import {Translator} from '@/hooks/useTranslatorAndReplacements'
import { Translator } from '@/hooks/useTranslatorAndReplacements'
import useVoronoiFinder from '@/hooks/useVoronoiFinder'
import useZoom from '@/hooks/useZoom'
import {Argument, Cluster, FavoritePoint, Point, PropertyMap, Result} from '@/types'
import {mean} from '@/utils'
import { Argument, Cluster, FavoritePoint, Point, PropertyMap, Result } from '@/types'
import { mean } from '@/utils'

type TooltipPosition = {
x: number
Expand All @@ -37,6 +38,8 @@ type MapProps = Result & {
question?: string
}
propertyMap: PropertyMap
paletteType: PaletteType
setPaletteType: (type: PaletteType) => void
}

function DotCircles(
Expand All @@ -54,7 +57,7 @@ function DotCircles(

return clusters.map((cluster) =>
cluster.arguments.filter(voteFilter.filter).map((arg) => {
const {arg_id, x, y} = arg
const { arg_id, x, y } = arg
const isCurrentTooltip = tooltip?.arg_id === arg_id

let dotClass = 'default'
Expand Down Expand Up @@ -138,8 +141,8 @@ function ClusterLabels(
key={cluster.cluster_id}
style={{
transform: 'translate(-50%, -50%)',
left: zoom.zoomX(scaleX(mean(cluster.arguments.map(({x}) => x)))),
top: zoom.zoomY(scaleY(mean(cluster.arguments.map(({y}) => y)))),
left: zoom.zoomX(scaleX(mean(cluster.arguments.map(({ x }) => x)))),
top: zoom.zoomY(scaleY(mean(cluster.arguments.map(({ y }) => y)))),
color: color(cluster.cluster_id, onlyCluster),
opacity: calculatedOpacity,
}}
Expand All @@ -162,15 +165,20 @@ function DesktopMap(props: MapProps) {
onlyCluster,
comments,
translator,
color,
color: initialColor, // renamed to avoid confusion
config,
propertyMap
propertyMap,
paletteType,
setPaletteType
} = props
const {dataHasVotes} = useInferredFeatures(props)
const { dataHasVotes } = useInferredFeatures(props)
const dimensions = useAutoResize(props.width, props.height)
const clusters = useRelativePositions(props.clusters)
const zoom = useZoom(dimensions, fullScreen)

// Use the color function passed from props
const color = initialColor

// for vote filter
const [minVotes, setMinVotes] = useState(0)
const [minConsensus, setMinConsensus] = useState(50)
Expand Down Expand Up @@ -229,8 +237,8 @@ function DesktopMap(props: MapProps) {
.map((c) => c.arguments.length)
.reduce((a, b) => a + b, 0)

const {scaleX, scaleY, width, height} = dimensions || {}
const {t} = translator
const { scaleX, scaleY, width, height } = dimensions || {}
const { t } = translator

const favoritesKey = `favorites_${window.location.href}`

Expand All @@ -244,7 +252,7 @@ function DesktopMap(props: MapProps) {
return []
}
})
const [zoomState, setZoomState] = useState({scale: 1, x: 0, y: 0})
const [zoomState, setZoomState] = useState({ scale: 1, x: 0, y: 0 })
const [isZoomEnabled] = useState(true)

useEffect(() => {
Expand All @@ -260,22 +268,22 @@ function DesktopMap(props: MapProps) {

const bind = useGesture(
{
onDrag: ({movement: [mx, my], cancel, direction: [dx, dy], memo}) => {
onDrag: ({ movement: [mx, my], cancel, direction: [dx, dy], memo }) => {
if (!isZoomEnabled) return memo
if (Math.abs(dy) > Math.abs(dx)) {
cancel() // ドラッグをキャンセルしてスクロールを許可
return memo
}
// 水平方向のドラッグの場合、地図のパンを処理
setZoomState((prev) => ({...prev, x: prev.x + mx, y: prev.y + my}))
setZoomState((prev) => ({ ...prev, x: prev.x + mx, y: prev.y + my }))
return memo
},
onPinch: ({offset: [d], memo}) => {
onPinch: ({ offset: [d], memo }) => {
const newScale = Math.min(Math.max(d, 0.5), 4)
setZoomState((prev) => ({...prev, scale: newScale}))
setZoomState((prev) => ({ ...prev, scale: newScale }))
return memo
},
onClick: ({event}) => {
onClick: ({ event }) => {
handleTap(event)
},
},
Expand All @@ -285,7 +293,7 @@ function DesktopMap(props: MapProps) {
threshold: 5,
},
pinch: {
scaleBounds: {min: 0.5, max: 4},
scaleBounds: { min: 0.5, max: 4 },
},
}
)
Expand All @@ -306,7 +314,7 @@ function DesktopMap(props: MapProps) {

if (!dimensions) return

const {width: dimensionsWidth, height: containerHeight} = dimensions
const { width: dimensionsWidth, height: containerHeight } = dimensions
const containerWidth = fullScreen ? dimensionsWidth * 0.75 : dimensionsWidth

const margin = fullScreen ? 0.6 : 0.8
Expand All @@ -323,7 +331,7 @@ function DesktopMap(props: MapProps) {

// zoomState が変更される場合のみ setZoomState を呼び出す
if (zoomState.scale !== scale || zoomState.x !== x || zoomState.y !== y) {
setZoomState({scale, x, y})
setZoomState({ scale, x, y })
}

}, [clusters, dimensions, fullScreen])
Expand Down Expand Up @@ -354,19 +362,19 @@ function DesktopMap(props: MapProps) {
if (y + TOOLTIP_HEIGHT > containerHeight) {
y = containerHeight - TOOLTIP_HEIGHT - TOOLTIP_MARGIN
}
return {x, y}
return { x, y }
}

console.warn('containerRef.current is undefined')
return {x: 0, y: 0}
return { x: 0, y: 0 }
}

if (!dimensions) {
console.log('NO DIMENSIONS???')
return (
<div
className="m-auto bg-blue-50"
style={{width: props.width, height: props.height}}
style={{ width: props.width, height: props.height }}
/>
)
}
Expand Down Expand Up @@ -431,7 +439,7 @@ function DesktopMap(props: MapProps) {

console.log(`Tap event at (${clientX}, ${clientY})`)

const clickedPoint = findPoint({clientX, clientY})
const clickedPoint = findPoint({ clientX, clientY })
if (clickedPoint) {
const newPosition = calculateTooltipPosition(clientX, clientY)
console.log('Tapped point found:', clickedPoint.data)
Expand Down Expand Up @@ -466,7 +474,7 @@ function DesktopMap(props: MapProps) {

return (
<>
<CustomTitle config={config}/>
<CustomTitle config={config} />
<div className="flex flex-1 relative">
{/* 地図コンテナ */}
<div
Expand Down Expand Up @@ -619,6 +627,8 @@ function DesktopMap(props: MapProps) {
minConsensus={minConsensus}
setMinConsensus={setMinConsensus}
voteFilter={voteFilter}
paletteType={paletteType}
setPaletteType={setPaletteType}
/>
)}
{/* お気に入り一覧 */}
Expand Down
Loading
Loading